public static NodeVersion MapTypedEntityForRevision(TypedEntity typedEntity, AbstractLookupHelper lookupHelper, AbstractMappingEngine masterMapper)
        {
            var mapped = new NodeVersion();

            MapTypedEntityForRevision(typedEntity, mapped, lookupHelper, masterMapper);
            return(mapped);
        }
        public static void MapFromRevision(IRevision <TypedEntity> source, NodeVersion destination, AbstractLookupHelper lookupHelper, AbstractMappingEngine masterMapper)
        {
            var masterNode = destination;

            if (masterNode == null)
            {
                MapTypedEntityForRevision(source.Item, lookupHelper, masterMapper);
            }
            else
            {
                MapTypedEntityForRevision(source.Item, masterNode, lookupHelper, masterMapper);
            }

            // Overwrite the default status history that was created by MapVersion
            // since in this mapping method, we actually have real revision info
            // The MapVersion method, in lieu of any data about a revision, adds a status history of "Created", which we can remove
            var revisionData = source.MetaData;

            var rdbmsStatusHistory   = CreateRdbmsStatusHistory(destination, revisionData, lookupHelper, masterMapper);
            var createdStatusHistory = destination.NodeVersionStatuses.FirstOrDefault(x => x.NodeVersionStatusType.Alias == FixedStatusTypes.Created.Alias);

            if (createdStatusHistory != null)
            {
                destination.NodeVersionStatuses.Remove(createdStatusHistory);
            }
            destination.NodeVersionStatuses.Add(rdbmsStatusHistory);
        }
Beispiel #3
0
        public TypedEntity MapTypedEntityForRevision(NodeVersion node, AbstractLookupHelper lookupHelper, AbstractMappingEngine masterMapper)
        {
            var mapped = new TypedEntity();

            MapTypedEntityForRevision(node, mapped, lookupHelper, masterMapper);
            return(mapped);
        }
Beispiel #4
0
        public Revision <TypedEntity> MapRevision(NodeVersion source, AbstractLookupHelper lookupHelper, AbstractMappingEngine masterMapper)
        {
            var output = new Revision <TypedEntity>();

            MapRevision(source, output, lookupHelper, masterMapper);
            return(output);
        }
Beispiel #5
0
 public RootLock(BPlusTree <TKey, TValue> tree, LockType type, bool exclusiveTreeAccess, string methodName)
 {
     tree.NotDisposed();
     _tree       = tree;
     _type       = type;
     _version    = type == LockType.Read ? tree._storage.CurrentVersion : null;
     _methodName = methodName;
     _exclusive  = exclusiveTreeAccess;
     _locked     = _exclusive ? _tree._selfLock.TryWrite(tree._options.LockTimeout) : _tree._selfLock.TryRead(tree._options.LockTimeout);
     LockTimeoutException.Assert(_locked);
     try
     {
         Pin = _tree._storage.LockRoot(type);
     }
     catch
     {
         if (_exclusive)
         {
             _tree._selfLock.ReleaseWrite();
         }
         else
         {
             _tree._selfLock.ReleaseRead();
         }
         throw;
     }
 }
        private IEnumerable <RevisionData> GetAllRevisionData(HiveId entityUri)
        {
            Mandate.ParameterNotEmpty(entityUri, "hiveId");

            //var entityStatusLog = Helper.NhSession.QueryOver<NodeVersionStatusHistory>()
            //    .OrderBy(x => x.Date).Desc
            //    .JoinQueryOver(x => x.NodeVersion).Where(x => x.Node.Id == (Guid)entityUri.Value)
            //    .List()
            //    .DistinctBy(x => x.Id);

            NodeVersionStatusHistory aliasHistory = null;
            NodeVersion           aliasVersion    = null;
            Node                  aliasNode       = null;
            NodeVersionStatusType aliasType       = null;
            var entityStatusLog = Helper.NhSession.QueryOver <NodeVersionStatusHistory>(() => aliasHistory)
                                  .OrderBy(x => x.Date).Desc
                                  .JoinQueryOver(x => x.NodeVersionStatusType, () => aliasType)
                                  .JoinQueryOver(x => aliasHistory.NodeVersion, () => aliasVersion)
                                  .JoinQueryOver(x => x.Node, () => aliasNode)
                                  .Where(x => x.Id == (Guid)entityUri.Value)
                                  .Fetch(x => aliasHistory.NodeVersionStatusType).Eager
                                  .Select(x => x.Date, x => x.Id, x => aliasNode.DateCreated, x => aliasType.Id, x => aliasType.IsSystem, x => aliasType.Alias, x => aliasType.Name, x => aliasVersion.Id)
                                  .List <object[]>()
                                  .Select(col => new
            {
                Date         = (DateTimeOffset)col[0],
                Id           = (Guid)col[1],
                DateCreated  = (DateTimeOffset)col[2],
                TypeId       = (Guid)col[3],
                TypeIsSystem = (bool)col[4],
                TypeAlias    = (string)col[5],
                TypeName     = (string)col[6],
                VersionId    = (Guid)col[7]
            });

            var otherRevisionData = new HashSet <RevisionData>();
            var changeset         = new Changeset(new Branch("default")); // Ignored for the moment in the persistence layer for this provider

            foreach (var statusQueryRow in entityStatusLog)
            {
                var nodeVersionStatusType = new NodeVersionStatusType
                {
                    Alias    = statusQueryRow.TypeAlias,
                    Name     = statusQueryRow.TypeName,
                    Id       = statusQueryRow.TypeId,
                    IsSystem = statusQueryRow.TypeIsSystem
                };

                var revisionStatusType = FrameworkContext.TypeMappers.Map <RevisionStatusType>(nodeVersionStatusType);
                var revisionData       = new RevisionData(changeset, (HiveId)statusQueryRow.VersionId, revisionStatusType)
                {
                    UtcCreated       = statusQueryRow.DateCreated,
                    UtcModified      = statusQueryRow.Date,
                    UtcStatusChanged = statusQueryRow.Date
                };

                otherRevisionData.Add(revisionData);
            }
            return(otherRevisionData);
        }
Beispiel #7
0
        public void MapRevision(NodeVersion source, Revision <TypedEntity> destination, AbstractLookupHelper lookupHelper, AbstractMappingEngine masterMapper)
        {
            if (destination.Item == null)
            {
                destination.Item = MapTypedEntityForRevision(source, lookupHelper, masterMapper);
            }
            else
            {
                MapTypedEntityForRevision(source, destination.Item, lookupHelper, masterMapper);
            }

            var latestStatus = GetLatestNodeVersionStatus(source, lookupHelper, masterMapper);

            var utcStatusChanged = latestStatus == null ? DateTimeOffset.MinValue : latestStatus.Date;
            var statusType       = latestStatus == null
                                 ? new RevisionStatusType("unknown", "Unknown / Not specified")
                                 : MapEntityStatusType(latestStatus.NodeVersionStatusType, lookupHelper, masterMapper);

            var metaData = new RevisionData()
            {
                Id               = (HiveId)source.Id,
                StatusType       = statusType,
                UtcCreated       = source.NodeVersionStatuses.First().Date,
                UtcModified      = utcStatusChanged,
                UtcStatusChanged = utcStatusChanged
            };

            destination.Item.UtcModified      = source.DateCreated;
            destination.Item.UtcStatusChanged = utcStatusChanged;
            destination.MetaData = metaData;
        }
 private static NodeVersionStatusHistory CreateRdbmsStatusHistory(NodeVersion destination, RevisionData revisionData, AbstractLookupHelper lookupHelper, AbstractMappingEngine masterMapper)
 {
     return(new NodeVersionStatusHistory()
     {
         Date = revisionData.UtcStatusChanged,
         NodeVersion = destination,
         NodeVersionStatusType = MapStatusType(revisionData.StatusType, lookupHelper, masterMapper)
     });
 }
        private static void MapVersion(TypedEntity source, NodeVersion destination, Node masterNode, AbstractLookupHelper lookupHelper, AbstractMappingEngine masterMapper)
        {
            destination.DateCreated = source.UtcModified;
            destination.Node        = masterNode;

            // First map the schema which will also map the attribute definitions
            var destinationSchema = MapAttributeSchemaDefinition(source.EntitySchema, lookupHelper, masterMapper);

            destination.AttributeSchemaDefinition = destinationSchema;

            //var rdbmsMappedAttributes = MapAttributes(source.Attributes, lookupHelper, masterMapper).ToList();
            //foreach (var rdbmsMappedAttribute in rdbmsMappedAttributes)
            //{
            //    // Ensure attribute has the AttributeDefinition instance created when mapping
            //    // the schema, to avoid saving duplicate definitions
            //    var attribute = rdbmsMappedAttribute;
            //    rdbmsMappedAttribute.AttributeDefinition = rdbmsSchema.AttributeDefinitions.Single(x => x.Alias == attribute.AttributeDefinition.Alias);
            //}

            MergeMapCollections(
                source.Attributes,
                destination.Attributes,
                (sourceTypedAttribute, dest) => MapAttribute(sourceTypedAttribute, dest, lookupHelper, masterMapper),
                sourceTypedAttribute => MapAttribute(sourceTypedAttribute, lookupHelper, masterMapper),
                (sourceAttrib, destAttrib) =>
            {
                destAttrib.NodeVersion = destination;

                // Support inherited properties: if the attribute definition has a schema on it, it's from another schema
                var inheritedDef = sourceAttrib.AttributeDefinition as InheritedAttributeDefinition;
                if (inheritedDef != null)
                {
                    var def = lookupHelper.Lookup <AttributeDefinition>(inheritedDef.Id);
                    if (def != null)
                    {
                        destAttrib.AttributeDefinition = def;
                    }
                }
                else
                {
                    destAttrib.AttributeDefinition = destinationSchema.AttributeDefinitions.Single(x => x.Alias == sourceAttrib.AttributeDefinition.Alias);
                }
            });

            //destination.Attributes.EnsureClearedWithProxy();
            //rdbmsMappedAttributes.ForEach(x =>
            //                                  {
            //                                      destination.Attributes.Add(x);
            //                                      x.NodeVersion = destination;
            //                                  });

            var revisionData       = new RevisionData(FixedStatusTypes.Created);
            var rdbmsStatusHistory = CreateRdbmsStatusHistory(destination, revisionData, lookupHelper, masterMapper);

            destination.NodeVersionStatuses.Add(rdbmsStatusHistory);
        }
            public void ChainTo(ref NodeVersion current)
            {
                NodeVersion last = this;

                while (last.Next != null)
                {
                    last = last.Next;
                }
                Interlocked.Exchange(ref current, last).Next = this;
            }
            public NodeCacheBase(BPlusTreeOptions <TKey, TValue> options)
            {
                Options     = options;
                LockFactory = Options.LockingFactory;
                Storage     = Options.CreateStorage();
                if (Options.UseStorageCache)
                {
                    Storage = new StorageCache(Storage, Options.CacheKeepAliveMaximumHistory);
                }

                NodeSerializer = new NodeSerializer(Options, new NodeHandleSerializer(Storage));
                _version       = new NodeVersion();
            }
        private bool TryUpdateExisting <T>(Revision <T> persistedEntity) where T : TypedEntity
        {
            var mappers = FrameworkContext.TypeMappers;

            if (persistedEntity.Item.Id.IsNullValueOrEmpty() && persistedEntity.MetaData.Id.IsNullValueOrEmpty())
            {
                return(false);
            }

            NodeVersion versionToEdit = null;

            if (!persistedEntity.MetaData.Id.IsNullValueOrEmpty())
            {
                // We're editing an existing revision
                versionToEdit = Helper.NhSession.Get <NodeVersion>((Guid)persistedEntity.MetaData.Id.Value);
            }

            if (versionToEdit == null)
            {
                var node = Helper.NhSession.Get <Node>((Guid)persistedEntity.Item.Id.Value);
                if (node == null)
                {
                    return(false);
                }

                // Since this is a new version we're adding to the db, ensure we haven't been given any attribute ids
                // that may affect another NodeVersion
                foreach (var attribute in persistedEntity.Item.Attributes)
                {
                    attribute.Id = HiveId.Empty;
                }

                versionToEdit      = mappers.Map <NodeVersion>(persistedEntity);
                versionToEdit.Node = node;

                // Save it so that we get an ID
                versionToEdit = Helper.NhSession.Merge(versionToEdit) as NodeVersion;
                // (APN 6/6/12) Dangerous: this will load all the NodeVersions for the node, which could be a lot, and it'll keep them in session too: node.NodeVersions.Add(versionToEdit);
            }
            else
            {
                // Map our incoming data onto the entity. No need to save anything as we're dealing only in entities that
                // were already in the session anyway
                mappers.Map(persistedEntity, versionToEdit, persistedEntity.GetType(), versionToEdit.GetType());
            }

            // Map the merge result back onto our incoming data to refresh it (with Ids, etc.)
            mappers.Map(versionToEdit, persistedEntity, versionToEdit.GetType(), persistedEntity.GetType());

            return(true);
        }
Beispiel #13
0
        public override T PerformExecuteScalar <T>(QueryDescription query, ObjectBinder objectBinder)
        {
            var revisionStatus = query.From.RevisionStatusType != FromClause.RevisionStatusNotSpecifiedType ? query.From.RevisionStatusType : null;

            NodeVersion outerVersionSelectorAlias = null;
            var         nodeIds = GetNodeIds(query);

            var aggQuery = Helper.GenerateAggregateStatusQuery(nodeIds, revisionStatus, true, query.SortClauses, query.From.HierarchyScope, query.From.ScopeStartIds, query.From.HierarchyType, query.From.ExcludeParentIds, query.From.ExcludeEntityIds);

            var filteredAggQuery = GetFilterQuery(query, aggQuery.GeneratedQuery);

            // If we're combining with a Skip or Take, we can't do a count inside the db
            var requiresLoadingIds = false;

            foreach (var filter in query.ResultFilters)
            {
                switch (filter.ResultFilterType)
                {
                case ResultFilterType.Take:
                    filteredAggQuery   = (IQueryOver <AggregateNodeStatus, AggregateNodeStatus>)filteredAggQuery.Take(filter.TakeCount);
                    requiresLoadingIds = true;
                    break;

                case ResultFilterType.Skip:
                    filteredAggQuery   = (IQueryOver <AggregateNodeStatus, AggregateNodeStatus>)filteredAggQuery.Skip(filter.SkipCount).Take(99999);  // Must include a Take in order for NH to generate the offset
                    requiresLoadingIds = true;
                    break;

                case ResultFilterType.Count:
                    var count = GetCount(filteredAggQuery, requiresLoadingIds);

                    return((T)(object)count);

                case ResultFilterType.Any:
                    var any = GetCount(filteredAggQuery, requiresLoadingIds) > 0;

                    return((T)(object)any);

                case ResultFilterType.All:
                    var countAll      = GetCount(aggQuery.GeneratedQuery, requiresLoadingIds);
                    var countFiltered = GetCount(filteredAggQuery, requiresLoadingIds);
                    var all           = countAll == countFiltered;

                    return((T)(object)all);
                }
            }

            var many = ExecuteMany <T>(query, objectBinder);

            return(many.Single());
        }
Beispiel #14
0
        //public IEnumerable<AttributeGroup> MapAttributeGroups(IEnumerable<AttributeDefinitionGroup> attributeDefinitionGroups)
        //{
        //    // For every item in the input parameter, select the result of the method MapAttributeGroup
        //    return attributeDefinitionGroups.Select(MapAttributeGroup);
        //}

        public void MapTypedEntityForRevision(NodeVersion source, TypedEntity destination, AbstractLookupHelper lookupHelper, AbstractMappingEngine masterMapper)
        {
            Mandate.ParameterNotNull(source, "source");
            Mandate.ParameterNotNull(destination, "destination");

            Node enclosingNode = source.Node;

            destination.EntitySchema = MapAttributeSchemaDefinition(source.AttributeSchemaDefinition, lookupHelper, masterMapper);

            // When we map the attributes, if any of them belong to schemas with another alias than the schema of this NodeVersion, then
            // those attributes must be "inherited" and we need to advertise that in the output model along with a reference to that schema too
            var allInheritedAttributes = source.Attributes.Where(x => x.AttributeDefinition.AttributeSchemaDefinition.Alias != source.AttributeSchemaDefinition.Alias).ToArray();
            var allRealAttributes      = source.Attributes.Except(allInheritedAttributes);

            var mappedRealAttributes      = MapAttributes(allRealAttributes, lookupHelper, masterMapper);
            var mappedInheritedAttributes =
                allInheritedAttributes.Select(
                    x => new { Original = x, Mapped = MapAttribute(x, lookupHelper, masterMapper) }).ToArray();

            // For the inherited ones, remap the AttributeDefinition
            foreach (var inherited in mappedInheritedAttributes)
            {
                var otherSchema = MapAttributeSchemaDefinition(inherited.Original.AttributeDefinition.AttributeSchemaDefinition, lookupHelper, masterMapper);
                inherited.Mapped.AttributeDefinition = new InheritedAttributeDefinition(inherited.Mapped.AttributeDefinition, otherSchema);
            }

            var collectionShouldValidateAgainstSchema = !allInheritedAttributes.Any();

            destination.Attributes.Reset(mappedRealAttributes.Concat(mappedInheritedAttributes.Select(x => x.Mapped)), collectionShouldValidateAgainstSchema);

            // Since this manual mapping stuff doesn't have a scope for avoiding remaps of the same object instance,
            // we need to go through and ensure we're using one group instance, so we'll use the one from the Schema
            foreach (var attribute in destination.Attributes)
            {
                var groupFromSchema = destination.EntitySchema.AttributeGroups.FirstOrDefault(x => x.Id == attribute.AttributeDefinition.AttributeGroup.Id);
                if (groupFromSchema != null)
                {
                    attribute.AttributeDefinition.AttributeGroup = groupFromSchema;
                }
            }

            destination.Id = new HiveId(enclosingNode.Id);

            destination.UtcCreated       = enclosingNode.DateCreated;
            destination.UtcModified      = source.DateCreated;
            destination.UtcStatusChanged = GetLatestStatusDate(source, lookupHelper, masterMapper);

            MapRelations(source.Node, destination, lookupHelper, masterMapper);
        }
 public static void Append <T>(ref T first, T version) where T : NodeVersion
 {
     if (first == null)
     {
         first = version;
     }
     else
     {
         NodeVersion last = first;
         while (last.Next != null)
         {
             last = last.Next;
         }
         last.Next = version;
     }
 }
Beispiel #16
0
 private static IQueryOver <AggregateNodeStatus, AggregateNodeStatus> AddSchemasToOuterQuery(IQueryOver <AggregateNodeStatus, AggregateNodeStatus> aggQuery, NhAggregateCriteriaVisitor.FilterResult filteringSubquery)
 {
     if (filteringSubquery.RequiredSchemaAliases != null && filteringSubquery.RequiredSchemaAliases.Any())
     {
         AttributeSchemaDefinition schema = null;
         NodeVersion v = null;
         aggQuery = aggQuery
                    .JoinAlias(x => x.NodeVersion, () => v)
                    .JoinAlias(() => v.AttributeSchemaDefinition, () => schema)
                    .Where(() => schema.Alias.IsIn(filteringSubquery.RequiredSchemaAliases.ToArray()));
     }
     if (filteringSubquery.RequiredNodeIds != null && filteringSubquery.RequiredNodeIds.Any())
     {
         aggQuery = aggQuery
                    .Where(x => x.Node.Id.IsIn(filteringSubquery.RequiredNodeIds.ToArray()));
     }
     return(aggQuery);
 }
        public IQueryOver <NodeVersion, NodeVersionStatusHistory> GenerateVersionedQueryPlusAttributes(Guid[] nodeIds = null, RevisionStatusType revisionStatus = null, bool limitToLatestRevision = true, IEnumerable <SortClause> sortClauses = null)
        {
            if (sortClauses == null)
            {
                sortClauses = Enumerable.Empty <SortClause>();
            }
            NodeVersion outerVersionSelect = null;
            var         outerQuery         = GenerateVersionedQuery(out outerVersionSelect, nodeIds, revisionStatus, limitToLatestRevision);

            Attribute                attribAlias              = null;
            AttributeDateValue       attributeDateValue       = null;
            AttributeDecimalValue    attributeDecimalValue    = null;
            AttributeIntegerValue    attributeIntegerValue    = null;
            AttributeStringValue     attributeStringValue     = null;
            AttributeLongStringValue attributeLongStringValue = null;

            outerQuery = outerQuery
                         .Left.JoinAlias(() => outerVersionSelect.Attributes, () => attribAlias) // Using a left join identifies to Nh that it can reuse the loaded Attributes because Nh considers them to be unaffected by the query, otherwise it issues another select from accessing NodeVersion.Attributes
                         .Left.JoinAlias(() => attribAlias.AttributeStringValues, () => attributeStringValue)
                         .Left.JoinAlias(() => attribAlias.AttributeLongStringValues, () => attributeLongStringValue)
                         .Left.JoinAlias(() => attribAlias.AttributeIntegerValues, () => attributeIntegerValue)
                         .Left.JoinAlias(() => attribAlias.AttributeDecimalValues, () => attributeDecimalValue)
                         .Left.JoinAlias(() => attribAlias.AttributeDateValues, () => attributeDateValue);

            //if (sortClauses.Any())
            //{
            //    AttributeDefinition attribDef = null;
            //    outerQuery = outerQuery.JoinAlias(() => attribAlias.AttributeDefinition, () => attribDef);
            //    foreach (var sortClause in sortClauses)
            //    {
            //        var coalesce = Projections.SqlFunction("coalesce", NHibernateUtil.String,
            //            Projections.Property(() => attributeStringValue.Value),
            //            Projections.Property(() => attributeLongStringValue.Value));
            //        if (sortClause.Direction == SortDirection.Ascending)
            //            outerQuery = outerQuery.OrderBy(coalesce).Asc;
            //        else
            //            outerQuery = outerQuery.OrderBy(coalesce).Desc;
            //    }
            //}

            return(outerQuery);
        }
Beispiel #18
0
        public UpgradeInfo Upgrade(String channel, String token)
        {
            var node = DecodeToken(token, Setting.Current.TokenSecret);

            if (node == null)
            {
                throw new ApiException(402, "节点未登录");
            }

            // 默认Release通道
            if (!Enum.TryParse <NodeChannels>(channel, true, out var ch))
            {
                ch = NodeChannels.Release;
            }
            if (ch < NodeChannels.Release)
            {
                ch = NodeChannels.Release;
            }

            // 找到所有产品版本
            var list = NodeVersion.GetValids(ch);

            // 应用过滤规则,使用最新的一个版本
            var pv = list.Where(e => e.Match(node)).OrderByDescending(e => e.Version).FirstOrDefault();

            if (pv == null)
            {
                return(null);
            }
            //if (pv == null) throw new ApiException(509, "没有升级规则");

            WriteHistory(node, "自动更新", true, $"channel={ch} => [{pv.ID}] {pv.Version} {pv.Source} {pv.Executor}");

            return(new UpgradeInfo
            {
                Version = pv.Version,
                Source = pv.Source,
                Executor = pv.Executor,
                Force = pv.Force,
                Description = pv.Description,
            });
        }
Beispiel #19
0
        public UpgradeInfo Upgrade(String channel)
        {
            var node = Session["Node"] as Node;

            if (node == null)
            {
                throw new ApiException(402, "节点未登录");
            }

            // 默认Release通道
            if (!Enum.TryParse <NodeChannels>(channel, true, out var ch))
            {
                ch = NodeChannels.Release;
            }
            if (ch < NodeChannels.Release)
            {
                ch = NodeChannels.Release;
            }

            // 找到所有产品版本
            var list = NodeVersion.GetValids(ch);

            // 应用过滤规则
            var pv = list.FirstOrDefault(e => e.Match(node));

            if (pv == null)
            {
                return(null);
            }
            //if (pv == null) throw new ApiException(509, "没有升级规则");

            WriteHistory("自动更新", true, node, $"channel={ch} => [{pv.ID}] {pv.Version} {pv.Source} {pv.Executor}");

            return(new UpgradeInfo
            {
                Version = pv.Version,
                Source = pv.Source,
                Executor = pv.Executor,
                Force = pv.Force,
                Description = pv.Description,
            });
        }
        public static void MapTypedEntityForRevision(TypedEntity source, NodeVersion destinationVersion, AbstractLookupHelper lookupHelper, AbstractMappingEngine masterMapper)
        {
            // Map the parent node of the node-version
            var enclosingNode = destinationVersion.Node;

            if (enclosingNode == null)
            {
                enclosingNode           = new Node();
                destinationVersion.Node = enclosingNode;
                enclosingNode.NodeVersions.Add(destinationVersion);
            }

            enclosingNode.DateCreated = source.UtcCreated;
            enclosingNode.Id          = (Guid)source.Id.Value;

            MapVersion(source, destinationVersion, enclosingNode, lookupHelper, masterMapper);
            //destinationNode.NodeVersions.Add(nodeVersion);

            MapRelations(enclosingNode, source, lookupHelper, masterMapper);
        }
        public NodeEvent GetEvent(ZWaveNode node, byte[] message)
        {
            NodeEvent nodeEvent = null;
            var       type      = (Command)message[1];

            if (type == Command.VersionReport)
            {
                var nodeVersion = new NodeVersion {
                    LibraryType           = message[2],
                    ProtocolVersion       = message[3],
                    ProtocolSubVersion    = message[4],
                    ApplicationVersion    = message[5],
                    ApplicationSubVersion = message[6]
                };
                node.Version = nodeVersion;
                nodeEvent    = new NodeEvent(node, EventParameter.VersionCommandClass, nodeVersion, 0);
            }

            if (type == Command.VersionCommandClassReport)
            {
                var cmdClass = (CommandClass)message[2];
                var value    = new VersionValue(cmdClass, message[3]);
                // Update node CC data
                if (cmdClass != CommandClass.NotSet)
                {
                    var nodeCc = node.GetCommandClass(cmdClass);
                    if (nodeCc != null)
                    {
                        nodeCc.Version = value.Version;
                    }
                    // Set the VersionCommandClass event
                    nodeEvent = new NodeEvent(node, EventParameter.VersionCommandClass, value, 0);
                }
                else
                {
                    Utility.logger.Warn("Command Class {0} ({1}) not supported yet", message[3], message[3].ToString("X2"));
                }
            }

            return(nodeEvent);
        }
Beispiel #22
0
        public UpgradeInfo Upgrade(String channel, String token)
        {
            var node = DecodeToken(token, Setting.Current.TokenSecret);

            if (node == null)
            {
                throw new ApiException(402, "节点未登录");
            }

            // 默认Release通道
            if (!Enum.TryParse <NodeChannels>(channel, true, out var ch))
            {
                ch = NodeChannels.Release;
            }
            if (ch < NodeChannels.Release)
            {
                ch = NodeChannels.Release;
            }

            // 找到所有产品版本
            var list = NodeVersion.GetValids(ch);

            // 应用过滤规则,使用最新的一个版本
            var pv = list.Where(e => e.Match(node)).OrderByDescending(e => e.Version).FirstOrDefault();

            if (pv == null)
            {
                return(null);
            }
            //if (pv == null) throw new ApiException(509, "没有升级规则");

            var url = pv.Version;

            if (!url.StartsWithIgnoreCase("http://", "https://"))
            {
                var uri = Request.GetRawUrl().ToString();
                var p   = uri.IndexOf('/', "https://".Length);
                if (p > 0)
                {
                    uri = uri[..p];
Beispiel #23
0
        public override T PerformExecuteScalar <T>(QueryDescription query, ObjectBinder objectBinder)
        {
            var disconnected   = new NhQueryOverVisitor().Visit(query.Criteria);
            var revisionStatus = query.From.RevisionStatusType != FromClause.RevisionStatusNotSpecifiedType ? query.From.RevisionStatusType : null;

            NodeVersion outerVersionSelectorAlias = null;
            var         nodeIds             = GetNodeIds(query);
            var         buildVersionedQuery = Helper.GenerateVersionedQueryPlusAttributes(nodeIds, revisionStatus: revisionStatus, limitToLatestRevision: true);

            switch (query.ResultFilter.ResultFilterType)
            {
            case ResultFilterType.Any:
                var queryOverAny = buildVersionedQuery.WithSubquery.WhereProperty(x => x.NodeVersion.Id).In(disconnected);
                return((T)(object)(queryOverAny.ToRowCountQuery().RowCount() != 0));

            case ResultFilterType.All:
                var queryOverAll     = buildVersionedQuery.WithSubquery.WhereProperty(x => x.NodeVersion.Id).In(disconnected);
                var totalRowCount    = Helper.NhSession.QueryOver <NodeVersion>().RowCountInt64();
                var filteredRowCount = queryOverAll.ToRowCountQuery().RowCountInt64();
                return((T)(object)(filteredRowCount > 0 && filteredRowCount == totalRowCount));

            case ResultFilterType.Count:
                // The query returns a cartesian product, so get the ids and count distinct in memory.
                // Later need to switch to a "count distinct" but SqlCe doesn't support it ffs

                var countQuery = buildVersionedQuery
                                 .WithSubquery.WhereProperty(x => x.NodeVersion.Id)
                                 .In(disconnected)
                                 .Select(x => x.Id);

                countQuery.UnderlyingCriteria.SetComment("For distinct counting");

                return((T)(object)countQuery.List <Guid>().Distinct().Count());
            }

            var many = ExecuteMany <T>(query, objectBinder);

            return(many.Single());
        }
Beispiel #24
0
        public NodeEvent GetEvent(ZWaveNode node, byte[] message)
        {
            NodeEvent nodeEvent = null;
            var type = (Command)message[1];

            if (type == Command.VersionReport)
            {
                var nodeVersion = new NodeVersion {
                    LibraryType = message[2],
                    ProtocolVersion = message[3],
                    ProtocolSubVersion = message[4],
                    ApplicationVersion = message[5],
                    ApplicationSubVersion = message[6]
                };
                node.Version = nodeVersion;
                nodeEvent = new NodeEvent(node, EventParameter.VersionCommandClass, nodeVersion, 0);
            }

            if (type == Command.VersionCommandClassReport)
            {
                var cmdClass = (CommandClass)message[2];
                var value = new VersionValue(cmdClass, message[3]);
                // Update node CC data
                if (cmdClass != CommandClass.NotSet)
                {
                    var nodeCc = node.GetCommandClass(cmdClass);
                    if (nodeCc != null)
                        nodeCc.Version = value.Version;
                    // Set the VersionCommandClass event
                    nodeEvent = new NodeEvent(node, EventParameter.VersionCommandClass, value, 0);
                }
                else
                {
                    Utility.logger.Warn("Command Class {0} ({1}) not supported yet", message[3], message[3].ToString("X2"));
                }
            }

            return nodeEvent;
        }
        public void AddAttributeValueFuturesToSession(Guid[] versionIds, NodeVersion outerVersionSelect)
        {
            Attribute            attribAlias    = null;
            Attribute            aliasForString = null;
            AttributeStringValue stringsLoader  = null;
            var strings = NhSession.QueryOver <Attribute>(() => attribAlias)
                          .Left.JoinAlias(() => attribAlias.AttributeStringValues, () => stringsLoader)
                          .Where(() => attribAlias.NodeVersion.Id.IsIn(versionIds))
                          .Future <Attribute>();

            Attribute            aliasForLongString = null;
            AttributeStringValue longStringsLoader  = null;
            var longStrings = NhSession.QueryOver <Attribute>(() => attribAlias)
                              .Left.JoinAlias(() => attribAlias.AttributeLongStringValues, () => longStringsLoader)
                              .Where(() => attribAlias.NodeVersion.Id.IsIn(versionIds))
                              .Future <Attribute>();

            Attribute             aliasForInteger = null;
            AttributeIntegerValue integerLoader   = null;
            var integers = NhSession.QueryOver <Attribute>(() => attribAlias)
                           .Left.JoinAlias(() => attribAlias.AttributeIntegerValues, () => integerLoader)
                           .Where(() => attribAlias.NodeVersion.Id.IsIn(versionIds))
                           .Future <Attribute>();

            Attribute             aliasForDecimal = null;
            AttributeDecimalValue decimalLoader   = null;
            var decimals = NhSession.QueryOver <Attribute>(() => attribAlias)
                           .Left.JoinAlias(() => attribAlias.AttributeDecimalValues, () => decimalLoader)
                           .Where(() => attribAlias.NodeVersion.Id.IsIn(versionIds))
                           .Future <Attribute>();

            Attribute          aliasForDate = null;
            AttributeDateValue dateLoader   = null;
            var dates = NhSession.QueryOver <Attribute>(() => attribAlias)
                        .Left.JoinAlias(() => attribAlias.AttributeDateValues, () => dateLoader)
                        .Where(() => attribAlias.NodeVersion.Id.IsIn(versionIds))
                        .Future <Attribute>();
        }
        public override Revision <TEntity> PerformGet <TEntity>(HiveId entityId, HiveId revisionId)
        {
            Mandate.ParameterNotEmpty(entityId, "entityId");
            Mandate.ParameterNotEmpty(revisionId, "revisionId");

            var revisionGuid = (Guid)revisionId.Value;
            var entityGuid   = (Guid)entityId.Value;


            NodeVersion outerVersionQuery = null;
            var         futureValue       = Helper.NhSession.QueryOver <NodeVersion>(() => outerVersionQuery)
                                            .Where(x => x.Id == revisionGuid).And(x => x.Node.Id == entityGuid)
                                            .Fetch(x => x.Node).Eager
                                            .Fetch(x => x.NodeVersionStatuses).Eager
                                            .FutureValue();

            Helper.AddAttributeValueFuturesToSession(new[] { revisionGuid });

            // Cause the multi-query to execute
            var entity = futureValue.Value;

            return(entity == null ? null : FrameworkContext.TypeMappers.Map <Revision <TEntity> >(entity));
        }
Beispiel #27
0
        public void SavingNodeVersion_ViaAddingToNodeCollection_UpdatesExistingInstance_WhenMerging()
        {
            var setup = new NhibernateTestSetupHelper();
            var node = new Node() { IsDisabled = false };

            using (var tran = setup.SessionForTest.BeginTransaction())
            {
                node = setup.SessionForTest.Merge(node) as Node;
                //setup.SessionForTest.SaveOrUpdate(node);
                tran.Commit();
            }

            Assert.That(node.Id, Is.Not.EqualTo(Guid.Empty));
            setup.SessionForTest.Clear();

            Assert.That(setup.SessionForTest.QueryOver<Node>().List().Count, Is.EqualTo(1));
            Assert.That(node.Id, Is.Not.EqualTo(Guid.Empty));

            NodeVersion nodeVersion = null;

            using (var tran = setup.SessionForTest.BeginTransaction())
            {
                // Get the node from the cleared session to mimic what the NH revision repository is doing
                node = setup.SessionForTest.Get<Node>(node.Id);

                var currentNodeId = node.Id;
                Assert.That(currentNodeId, Is.Not.EqualTo(Guid.Empty));

                var schema = new AttributeSchemaDefinition { Alias = "tes1", SchemaType = "content" };
                nodeVersion = new NodeVersion { DefaultName = "test", Node = node, AttributeSchemaDefinition = schema };

                nodeVersion = setup.SessionForTest.Merge(nodeVersion) as NodeVersion;


                node.NodeVersions.Add(nodeVersion);
                
                node = setup.SessionForTest.Merge(node) as Node;

                tran.Commit();
                Assert.That(currentNodeId, Is.EqualTo(node.Id));
                Assert.That(node.NodeVersions.Count, Is.EqualTo(1));
                Assert.That(node.NodeVersions.First().Id, Is.EqualTo(nodeVersion.Id));
                Assert.That(nodeVersion.Id, Is.Not.EqualTo(Guid.Empty));
            }

            setup.SessionForTest.Clear();

            Assert.That(setup.SessionForTest.QueryOver<Node>().List().Count, Is.EqualTo(2)); // One for the Node, one for the Schema
            Assert.That(node.Id, Is.Not.EqualTo(Guid.Empty));

            node = setup.SessionForTest.Get<Node>(node.Id);

            Assert.That(node.NodeVersions, Is.Not.Empty);
            Assert.That(node.NodeVersions.Count, Is.EqualTo(1));
            Assert.That(nodeVersion.Id, Is.Not.EqualTo(Guid.Empty));
            Assert.That(node.NodeVersions.First().Id, Is.EqualTo(nodeVersion.Id));
        }
 public void ReturnVersion(ref NodeVersion ver) /*if (_version is NodePin) new NodeVersion().ChainTo(ref _version);*/ GC
 public void AddVersion(NodeVersion version)
 {
     version.ChainTo(ref _version);
 }
Beispiel #30
0
 private NodeVersionStatusHistory GetLatestNodeVersionStatus(NodeVersion source, AbstractLookupHelper lookupHelper, AbstractMappingEngine masterMapper)
 {
     return(source.NodeVersionStatuses.OrderByDescending(x => x.Date).FirstOrDefault());
 }
        public IQueryOver <NodeVersion, NodeVersionStatusHistory> GenerateVersionedQuery(out NodeVersion outerVersionSelectAlias, Guid[] nodeIds = null, RevisionStatusType revisionStatus = null, bool limitToLatestRevision = true)
        {
            // We want the NodeVersion table, joined to the NodeVersionStatusHistory table,
            // ordered by the status history date descending, but we only want the latest one

            Node        node             = null;
            NodeVersion subSelectVersion = null;
            NodeVersionStatusHistory subSelectTopStatus = null;
            NodeVersion           outerVersionSelect    = null;
            NodeVersionStatusType subSelectStatusType   = null;

            // First define the subselection of the top 1 version items when joined and sorted by version status history in date-descending order
            // We also add a clause to say "where the outer selected version's node id equals the subselected node id" since it's selecting the top 1
            // so we want it to be the 1 latest-date item relevant for each row of the outer select
            var subSelectTopStatusByDate = QueryOver.Of(() => subSelectTopStatus)
                                           //.Where(() => subSelectTopStatus.NodeVersion.Id == outerVersionSelect.Id);
                                           .JoinQueryOver(() => subSelectTopStatus.NodeVersion, () => subSelectVersion)
                                           .JoinQueryOver(() => subSelectVersion.Node, () => node)
                                           .Where(() => subSelectTopStatus.NodeVersion.Id == subSelectVersion.Id)
                                           .And(() => outerVersionSelect.Node.Id == node.Id);

            int takeCount = limitToLatestRevision ? 1 : 999;

            // Now we need to add a filter for the revision status type, if one was supplied
            QueryOver <NodeVersionStatusHistory> subSelectTopStatusByDateWithFilter = null;
            QueryOver <NodeVersionStatusHistory> excludeNegatingStatusses           = null;

            if (revisionStatus != null)
            {
                var statusAlias = revisionStatus.Alias;

                if (revisionStatus.NegatedByTypes.Any())
                {
                    NodeVersionStatusHistory negateHistory = null;
                    NodeVersionStatusType    negateType    = null;
                    NodeVersion negateVersion   = null;
                    var         negatingAliases = revisionStatus.NegatedByTypes.Select(x => x.Alias).ToArray();

                    //var first = negatingAliases.First();
                    excludeNegatingStatusses = QueryOver.Of(() => negateHistory)
                                               .JoinAlias(() => negateHistory.NodeVersionStatusType, () => negateType)
                                               .JoinAlias(() => negateHistory.NodeVersion, () => negateVersion)
                                               .Where(() => negateType.Alias.IsIn(negatingAliases))
                                               .And(() => outerVersionSelect.Node == negateVersion.Node)
                                               .Select(Projections.SqlFunction("coalesce", NHibernateUtil.DateTime, Projections.Max <NodeVersionStatusHistory>(x => x.Date), new ConstantProjection(new DateTime(1981, 8, 1))));

                    //excludeNegatingStatusses = QueryOver.Of(() => negateHistory)
                    //    .JoinAlias(() => negateHistory.NodeVersionStatusType, () => negateType)
                    //    .JoinAlias(() => negateHistory.NodeVersion, () => negateVersion)
                    //    .JoinAlias(() => negateVersion.Node, () => node)
                    //    .Where(() => negateType.Alias.IsIn(negatingAliases))
                    //    .And(() => negateHistory.Date > subSelectTopStatus.Date)
                    //    //.And(() => subSelectTopStatus.NodeVersion.Id == negateVersion.Id)
                    //    .And(() => outerVersionSelect.Node.Id == node.Id)
                    //    .Select(x => x.Id)
                    //    .Take(1);

                    //excludeNegatingStatusses = QueryOver.Of(() => negateHistory)
                    //    .JoinAlias(() => negateHistory.NodeVersionStatusType, () => negateType)
                    //    .JoinAlias(() => negateHistory.NodeVersion, () => negateVersion)
                    //    .JoinAlias(() => negateVersion.Node, () => node)
                    //    .Where(() => negateType.Alias.IsIn(negatingAliases))
                    //    .And(() => outerVersionSelect.Node.Id == node.Id)
                    //    .And(() => negateHistory.Date > subSelectTopStatus.Date)
                    //    .OrderBy(x => x.Date).Desc
                    //    .Select(x => x.Id)
                    //    .Take(1);
                }

                var subSelectBuilder = subSelectTopStatusByDate
                                       .And(() => subSelectStatusType.Alias == statusAlias)
                                       .JoinQueryOver(x => subSelectTopStatus.NodeVersionStatusType, () => subSelectStatusType)
                                       .OrderBy(() => subSelectTopStatus.Date).Desc;

                if (excludeNegatingStatusses != null)
                {
                    // Yeah, I know, horrible to check Sql dialect when generating query, but Nh's dialect support doesn't allow a provider-based
                    // way of telling whether the db engine supports / requires "all" to be prefix before a subquery when doing an operation.
                    // e.g. SqlCe requires "blah > all (select max(blah) from blah)", SqlServer doesn't mind, SQLite doesn't support it
                    if (RequiresAllForGtSubquery())
                    {
                        subSelectBuilder = subSelectBuilder.WithSubquery.WhereProperty(() => subSelectTopStatus.Date).GtAll(excludeNegatingStatusses);
                    }
                    else
                    {
                        subSelectBuilder = subSelectBuilder.WithSubquery.WhereProperty(() => subSelectTopStatus.Date).Gt(excludeNegatingStatusses);
                    }

                    //subSelectBuilder = subSelectBuilder.WithSubquery.WhereNotExists(excludeNegatingStatusses);
                    //subSelectBuilder = subSelectBuilder.WithSubquery.WhereProperty(() => subSelectTopStatus.Id).NotIn(excludeNegatingStatusses);
                }

                subSelectTopStatusByDateWithFilter = subSelectBuilder.Select(x => subSelectTopStatus.NodeVersion.Id).Take(takeCount);
                // We have to include a Take here for compatibility with SqlServerCe
            }
            else
            {
                subSelectTopStatusByDateWithFilter = subSelectTopStatusByDate
                                                     .OrderBy(() => subSelectTopStatus.Date).Desc
                                                     .Select(x => subSelectTopStatus.NodeVersion.Id).Take(takeCount);
                // We have to include a Take here for compatibility with SqlServerCe
            }

            NodeVersionStatusHistory outerHistoryForSort = null;
            IQueryOver <NodeVersion, NodeVersionStatusHistory> outerQuery = NhSession.QueryOver <NodeVersion>(
                () => outerVersionSelect)
                                                                            //.Fetch(x => x.AttributeSchemaDefinition).Eager
                                                                            .Fetch(x => x.Attributes).Eager
                                                                            // We load these eagerly rather than in a Future to avoid a separate query
                                                                            .Fetch(x => x.Node).Eager
                                                                            // There's a 1-m mapping between Node-NodeVersion so safe to load this with a join too rather than with a future
                                                                            .Inner.JoinQueryOver(x => outerHistoryForSort.NodeVersionStatusType, () => subSelectStatusType)
                                                                            .Inner.JoinQueryOver(x => outerVersionSelect.NodeVersionStatuses, () => outerHistoryForSort);

            NodeVersion innerVersion = null;
            NodeVersionStatusHistory innerHistory = null;
            NodeVersionStatusType    innerType    = null;
            var buildInnerHistorySubQuery         = QueryOver.Of <NodeVersionStatusHistory>(() => innerHistory)
                                                    .JoinQueryOver(() => innerHistory.NodeVersion, () => innerVersion)
                                                    .JoinQueryOver(() => innerHistory.NodeVersionStatusType, () => innerType)
                                                    .Where(() => innerVersion.Node == outerVersionSelect.Node);

            if (revisionStatus != null)
            {
                var statusAlias = revisionStatus.Alias;
                buildInnerHistorySubQuery = buildInnerHistorySubQuery
                                            .And(() => innerType.Alias == statusAlias);

                NodeVersionStatusType reselectType = null;
                outerQuery = outerQuery
                             .And(() => subSelectStatusType.Alias == statusAlias);

                // Yeah, I know, horrible to check Sql dialect when generating query, but Nh's dialect support doesn't allow a provider-based
                // way of telling whether the db engine supports / requires "all" to be prefix before a subquery when doing an operation.
                // e.g. SqlCe requires "blah > all (select max(blah) from blah)", SqlServer doesn't mind, SQLite doesn't support it
                if (excludeNegatingStatusses != null)
                {
                    if (RequiresAllForGtSubquery())
                    {
                        outerQuery = outerQuery.WithSubquery.WhereProperty(() => outerHistoryForSort.Date).GtAll(excludeNegatingStatusses);
                    }
                    else
                    {
                        outerQuery = outerQuery.WithSubquery.WhereProperty(() => outerHistoryForSort.Date).Gt(excludeNegatingStatusses);
                    }
                }
            }

            var subQueryInnerHistory = buildInnerHistorySubQuery.Select(x => x.Id)
                                       .OrderBy(() => innerHistory.Date).Desc
                                       .Take(takeCount);

            outerQuery = outerQuery
                         .OrderBy(() => outerHistoryForSort.Date).Asc
                         .WithSubquery.WhereProperty(() => outerHistoryForSort.Id).In(subQueryInnerHistory);

            //// Based on perf testing of SqlCe queries, it shaves a lot off execution time if we specify the status type in the
            //// outer query in addition to the subquery
            //if (revisionStatus != null)
            //{
            //    var statusAlias = revisionStatus.Alias;
            //    outerQuery = outerQuery
            //        .And(x => subSelectStatusType.Alias == statusAlias);
            //}

            //outerQuery = outerQuery
            //    .OrderBy(() => outerHistoryForSort.Date).Asc
            //    .WithSubquery.WhereProperty(() => outerVersionSelect.Id).In(subSelectTopStatusByDateWithFilter.Clone());

            if (nodeIds != null && nodeIds.Any())
            {
                outerQuery = outerQuery.And(() => outerVersionSelect.Node.Id.IsIn(nodeIds));
            }

            outerVersionSelectAlias = outerVersionSelect;
            return(outerQuery);
        }
Beispiel #32
0
        public void WhenAddingNodeVersionToSession_ThenClearingAndResettingAttributesCollection_BeforeCommitting_AttributesCollectionIsCorrect()
        {
            var setup = new NhibernateTestSetupHelper();
            var node = new Node() { IsDisabled = false };

            using (var tran = setup.SessionForTest.BeginTransaction())
            {
                node = setup.SessionForTest.Merge(node) as Node;
                tran.Commit();
            }
            setup.SessionForTest.Clear();

            NodeVersion nodeVersion = null;

            using (var tran = setup.SessionForTest.BeginTransaction())
            {
                // Get the node from the cleared session to mimic what the NH revision repository is doing
                node = setup.SessionForTest.Get<Node>(node.Id);

                var currentNodeId = node.Id;
                Assert.That(currentNodeId, Is.Not.EqualTo(Guid.Empty));

                var schema = new AttributeSchemaDefinition { Alias = "tes1", SchemaType = "content" };
                var type = new AttributeType { Alias = "type1" };
                var def = new AttributeDefinition
                    { Alias = "def1", AttributeDefinitionGroup = new AttributeDefinitionGroup { Alias = "group1", AttributeSchemaDefinition = schema}, AttributeSchemaDefinition = schema, AttributeType = type};
                schema.AttributeDefinitions.Add(def);
                nodeVersion = new NodeVersion { DefaultName = "test", Node = node, AttributeSchemaDefinition = schema };
                nodeVersion.Attributes.Add(new Attribute { AttributeDefinition = def, NodeVersion = nodeVersion });
                nodeVersion.Node = node;

                // Merge the version into the session, which will add it to 1st-level cache but we haven't committed to db yet
                nodeVersion = setup.SessionForTest.Merge(nodeVersion) as NodeVersion;

                var persister = setup.SessionForTest.GetSessionImplementation().PersistenceContext;

                nodeVersion.Attributes.Clear();
                nodeVersion.Attributes.Add(new Attribute { AttributeDefinition = def, NodeVersion = nodeVersion });

                nodeVersion = setup.SessionForTest.Merge(nodeVersion) as NodeVersion;

                node.NodeVersions.Add(nodeVersion);

                setup.SessionForTest.Merge(node);

                tran.Commit();
            }
            setup.SessionForTest.Clear();

            using (var tran = setup.SessionForTest.BeginTransaction())
            {
                var reloadVersion = setup.SessionForTest.Get<NodeVersion>(nodeVersion.Id);
                reloadVersion.Attributes.Clear();
                setup.SessionForTest.Merge(reloadVersion);
                tran.Commit();
            }

            using (var tran = setup.SessionForTest.BeginTransaction())
            {
                var reloadVersion = setup.SessionForTest.Get<NodeVersion>(nodeVersion.Id);
                Assert.That(reloadVersion.Attributes.Count, Is.EqualTo(1));
            }
        }
Beispiel #33
0
 private DateTimeOffset GetLatestStatusDate(NodeVersion source, AbstractLookupHelper lookupHelper, AbstractMappingEngine masterMapper)
 {
     return(source.NodeVersionStatuses.OrderByDescending(x => x.Date).Select(x => x.Date).FirstOrDefault());
 }