/// <summary>
        /// Calculates the surrogates to be persisted or removes the ones that do not have valid references
        /// </summary>
        public void CalculateSurrogatesToBePersisted()
        {
            var currentSurrogates = new StateObjectSurrogate[_surrogates.Values.Count];

            _surrogates.Values.CopyTo(currentSurrogates, 0);
            bool removedSurrogate;

            //Step 1. Make sure that the surrogates have valid references, otherwise are removed.
            do
            {
                removedSurrogate = false;
                for (int i = currentSurrogates.Length - 1; i >= 0; i--)
                {
                    var surrogate = currentSurrogates[i];
                    if (surrogate == null)
                    {
                        continue;
                    }
                    lock (surrogate)
                    {
                        if (!surrogate.ShouldBeSerialized())
                        {
                            currentSurrogates[i] = null;
                            removedSurrogate     = true;
                            //The surrogate won't persist and will be removed from the storage if present.
                            _stateManager.RemoveObject(surrogate.UniqueID, false, true);
                        }
                    }
                }
            } while (removedSurrogate);
            //Step 2. Was there are removed surrogate? then make sure the remaining where not dependent of them.
            //No removed surrogates then this is the final list.
            _surrogatesToBePersisted = currentSurrogates;
        }
 internal IStateObject GetSurrogateFirstReference(StateObjectSurrogate obj)
 {
     lock (obj)
     {
         return(_stateManager.GetObject(obj.objectRefs[0].UniqueID));
     }
 }
 internal void AddSurrogateReference(StateObjectSurrogate surrogate, IStateObject reference)
 {
     lock (surrogate)
     {
         surrogate.AddReference(new LazyStateObjectReference(_stateManager, reference));
     }
 }
Example #4
0
        /// <summary>
        /// Sometimes while serializing a "DisplayClass" we might find fields that reference
        /// IStateObjects.
        /// Promises are persisted using the Surrogates mechanism, and we also are aware that
        /// Surrogates are the last thing to be serialized.
        /// Processes like adoption occur even before StateManager.Persist is started.
        /// When the value for these fields are serialized, it might happen that there are still "unattached"
        /// so they need to be adopted
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="value"></param>
        internal StateObjectSurrogate GetOrphanHolder(object instance, IStateObject value, string fieldName)
        {
            if (!StateManager.AllBranchesAttached(value.UniqueID))
            {
                var displayClassSurrogate = _stateManager.surrogateManager.GetSurrogateFor(instance, generateIfNotFound: false);
                if (displayClassSurrogate == null)
                {
                    throw new InvalidOperationException("A surrogate is needed");
                }

                //Retrieve surrogate
                StateObjectSurrogate surrogate = (StateObjectSurrogate)_stateManager.surrogateManager.GetSurrogateFor(value, generateIfNotFound: true);
                if (surrogate == null)
                {
                    throw new Exception("Object must be instantiated/registered with resolve");
                }
                //Add reference if needed
                _stateManager.surrogateManager.AddSurrogateReference(surrogate, displayClassSurrogate.UniqueID);
                AddSurrogateHolder(surrogate);
                return(surrogate);
            }
            else
            {
                return(null);
            }
        }
 public void RemoveSurrogateReference(StateObjectSurrogate surrogate, IStateObject oldReference)
 {
     if (oldReference != null && surrogate != null)
     {
         RemoveSurrogateReference(surrogate, oldReference.UniqueID);
     }
 }
 internal void AddSurrogateReference(StateObjectSurrogate surrogate, string uniqueId)
 {
     lock (surrogate)
     {
         surrogate.AddReference(new LazyStateObjectReference(_stateManager, uniqueId));
     }
 }
        /// <summary>
        /// Retrieves or creates a surrogate object for a value
        /// </summary>
        /// <param name="newValueObject"></param>
        /// <param name="generateIfNotFound"></param>
        /// <returns></returns>
        private StateObjectSurrogate GetSurrogateForBeforePersist(object newValueObject, bool generateIfNotFound, string parentSurrogate = null)
        {
#if DEBUG
            Debug.Assert(newValueObject != null, "Surrogates cannot be registered for null values");
#endif

            StateObjectSurrogate surrogate;
            lock (this)
            {
                if (_surrogates.TryGetValue(newValueObject, out surrogate))
                {
                    return(surrogate);
                }
                if (generateIfNotFound)
                {
#if DEBUG
                    if (AllDependenciesAreProcessed)
                    {
                        Debug.WriteLine("Invalid surrogate reference. This might be caused by a calculated property that is being call to get an object JSON. Please analyze the callstack and make the proper code changes.\r\nCall Stack: \r\n: {0}", new StackTrace(true).ToString());
                    }
#endif
                    surrogateDirectoryLock.EnterUpgradeableReadLock();
                    try
                    {
                        surrogateDirectoryLock.EnterWriteLock();
                        try
                        {
                            var parentSurrogateUniqueID = (parentSurrogate == null ? "" : UniqueIDGenerator.UniqueIdSeparator + parentSurrogate);
                            _surrogates.Add(newValueObject,
                                            surrogate =
                                                new StateObjectSurrogate
                            {
                                UniqueID = "!" + _stateManager.UniqueIDGenerator.GetUniqueID() + parentSurrogateUniqueID,
                                Value    = newValueObject
                            });

                            //REMOVE _stateManager.AddNewObject(surrogate); //TODO Add in stateManager not mark as dirty because all surrogates are dirty
                            //We need to add the uniqueID to the surrogatesIdsToSurrogates
                            //because this table is used to match surrogates instances to their
                            //corresponding uniqueid because obviously surrogates do not have the uniqueId property
                            _surrogatesIdsToSurrogates.Add(surrogate.UniqueID, surrogate);
                        }
                        finally
                        {
                            surrogateDirectoryLock.ExitWriteLock();
                        }
                    }
                    finally
                    {
                        surrogateDirectoryLock.ExitUpgradeableReadLock();
                    }
                    //Trace.TraceInformation("A new surrogate ID {0} for object of type {1} has been created", surrogate.UniqueID, newValueObject.GetType());
                }
            }
            return(surrogate);
        }
 public void RemoveSurrogateReference(StateObjectSurrogate surrogate, string uniqueIdOfLastReferent)
 {
     lock (surrogate)
     {
         surrogate.RemoveReference(uniqueIdOfLastReferent);
         if (surrogate.objectRefs.Count == 0)
         {
             _stateManager.RemoveObject(surrogate.UniqueID, true);
         }
     }
 }
        private void GetResolvedValueEx(DependencyResolutionInfo dependency)
        {
            var surrogateManager  = _stateManager.surrogateManager;
            var value             = dependency.value;
            var istateObjectValue = dependency.value as IStateObject;

            if (istateObjectValue != null)
            {
                //The value is an state object
                if (_stateManager.IsInElementsToRemove(istateObjectValue.UniqueID))
                {
                    //If the object is present in the elements it is detached from so its UniqueID
                    //is changed to a temporal one.
                    //The current in the session must be removed
                    _stateManager.DettachObject(istateObjectValue);
                }
                dependency.canBeAnOrphan = !StateManager.AllBranchesAttached(istateObjectValue);
                dependency.ResolvedValue = istateObjectValue;
                dependency.IsStateObject = true;
            }
            else if (value is ISurrogateEventsInfo)
            {
                dependency.ResolvedValue = value;
                dependency.isEventsInfo  = true;
            }
            else
            {
                //if (surrogateManager.IsSurrogateRegistered(value.GetType())) Commented for performance
                StateObjectSurrogate currentSurrogate = null;
                //Get the surrogate instance from the surrogates that are already loaded in memory or create one
                dependency.ResolvedValue = currentSurrogate = dependency.ResolvedSurrogate = surrogateManager.GetSurrogateFor(value, generateIfNotFound: true);

                if (currentSurrogate == null)
                {
                    throw new ArgumentException("A surrogate could not be gotten for value of type " + value.GetType().FullName);
                }

                if (_stateManager.IsInElementsToRemove(currentSurrogate.UniqueID))
                {
                    //If the object is present in the elements it is restored,
                    //since it is a top element no adoption needs to be performed
                    _stateManager.UndoRemove(currentSurrogate.UniqueID);
                    //We must unremove the Value surrogate
                    var valueUniqueID = UniqueIDGenerator.GetRelativeUniqueID(currentSurrogate, StateObjectSurrogate.VALUE_PREFIX);
                    _stateManager.UndoRemove(valueUniqueID);
                }
                else
                {
                    //OK
                }
            }
        }
Example #10
0
        public void SaveSurrogate(StateObjectSurrogate surrogate)
        {
            //Save surrogate header
            var surrogateContext = StateManager.Current.surrogateManager.GetSurrogateContext(surrogate.UniqueID, surrogate);
            var raw = SurrogatesDirectory.ObjectToRaw(surrogate, surrogateContext);

            SaveRaw(surrogate.UniqueID, raw);

            //Save surrogate value
            var uid = UniqueIDGenerator.GetRelativeUniqueID(surrogate, StateObjectSurrogate.VALUE_PREFIX);

            surrogateContext = StateManager.Current.surrogateManager.GetSurrogateContext(uid, surrogate.Value);
            raw = SurrogatesDirectory.ObjectToRaw(surrogate.Value, surrogateContext);
            SaveRaw(uid, raw);
        }
Example #11
0
        public void SaveSurrogate(StateObjectSurrogate surrogate)
        {
            //Saving surrogate header
            var surrogatecontext = _surrogateManager.GetSurrogateContext(surrogate.UniqueID, surrogate);
            var raw = SurrogatesDirectory.ObjectToRaw(surrogate, surrogatecontext);

            SaveRaw(surrogate.UniqueID, raw);
            //Saving surrogateValue
            if (surrogate.ShouldSerializeValue)
            {
                var uid = UniqueIDGenerator.GetRelativeUniqueID(surrogate, StateObjectSurrogate.VALUE_PREFIX);
                surrogatecontext = _surrogateManager.GetSurrogateContext(uid, surrogate.Value);
                raw = SurrogatesDirectory.ObjectToRaw(surrogate.Value, surrogatecontext);
                SaveRaw(uid, raw);
            }
        }
 /// <summary>
 /// Registers which pointers are using this surrogate.
 /// This is important because a surrogate with no references should be deleted
 /// </summary>
 /// <param name="surrogate"></param>
 /// <param name="pointer"></param>
 /// <param name="isNewPointer"></param>
 internal void AddSurrogateReference(StateObjectSurrogate surrogate, StateObjectPointer pointer, bool isNewPointer = true)
 {
     //Check if reference already exits
     lock (surrogate)
     {
         surrogate.AddReference(new LazyStateObjectReference(_stateManager, pointer));
     }
     //RegisterSurrogatedObject(surrogate, pointer.UniqueID);
     pointer.Target = surrogate;
     if (isNewPointer)
     {
         _stateManager.AddNewObject(pointer);
     }
     else if (StateManager.AllBranchesAttached(pointer))
     {
         _stateManager.StorageManager.SaveObject(pointer);
     }
     _stateManager.UndoRemove(pointer.UniqueID);
 }
 private object GetResolvedValue(object value)
 {
     if (value == null)
     {
         return(value);
     }
     if (_stateManager.surrogateManager.IsSurrogateRegistered(value.GetType()))
     {
         StateObjectSurrogate currentSurrogate = null;
         if (_stateManager.surrogateManager.GetSurrogates().TryGetValue(value, out currentSurrogate))
         {
             return(currentSurrogate);
         }
         else
         {
             return(null);
         }
     }
     else
     {
         return(value);
     }
 }
        private StateObjectSurrogate GetSurrogateForAfterPersist(object newValueObject, bool generateIfNotFound, string parentSurrogate = null)
        {
            StateObjectSurrogate surrogate;

            lock (this)
            {
                if (_surrogates.TryGetValue(newValueObject, out surrogate))
                {
                    //The surrogate could exist but it was not worthy of serialization
                    //In old times, surrogates were in charge of serialization and reference management
                    //Now these dependencies are handle in the SurrogateDependencyManager.
                    //So we now asumme we should not validate if the surrogate is worthy or not.
                    return(surrogate);
                }
                if (generateIfNotFound)
                {
#if DEBUG
                    if (AllDependenciesAreProcessed)
                    {
                        Debug.WriteLine("Invalid surrogate reference. This might be caused by a calculated property that is being call to get an object JSON. Please analyze the callstack and make the proper code changes.\r\nCall Stack: \r\n: {0}", new StackTrace(true).ToString());
                    }
#endif


                    //was it that it is present but was not worthy?
                    if (surrogate != null)
                    {
                        if (lastMinuteSurrogates == null || !lastMinuteSurrogates.Contains(surrogate))
                        {
                            //We need to update the UniqueID
                            if (parentSurrogate != null)
                            {
                                surrogate.UniqueID = "!" + _stateManager.UniqueIDGenerator.GetUniqueID() + UniqueIDGenerator.UniqueIdSeparator + parentSurrogate;

                                if (surrogate.UniqueID.StartsWith("!r"))
                                {
                                    Trace.WriteLine("Surrogate = " + surrogate.UniqueID);
                                    Trace.WriteLine(new StackTrace(true).ToString());
                                }



                                _surrogates[surrogate.Value] = surrogate;
                                _surrogatesIdsToSurrogates[surrogate.UniqueID] = surrogate;
                            }
                        }
                    }
                    else
                    {
                        var parentSurrogateUniqueID = (parentSurrogate == null ? "" : UniqueIDGenerator.UniqueIdSeparator + parentSurrogate);
                        _surrogates.Add(newValueObject,
                                        surrogate =
                                            new StateObjectSurrogate
                        {
                            UniqueID = "!" + _stateManager.UniqueIDGenerator.GetUniqueID() + parentSurrogateUniqueID,
                            Value    = newValueObject
                        });


                        _surrogatesIdsToSurrogates.Add(surrogate.UniqueID, surrogate);
                    }
                    //Add to last minute surrogate
                    lastMinuteSurrogates = lastMinuteSurrogates ?? new HashSet <StateObjectSurrogate>(ComparerByReference.CommonInstance);
                    if (parentSurrogate != null)
                    {
                        _stateManager.surrogateManager.AddSurrogateReference(surrogate, parentSurrogate);
                    }
                    lastMinuteSurrogates.Add(surrogate);
                }
            }
            return(surrogate);
        }
Example #15
0
 public void SendToSurrogatesToBePersisted(StateObjectSurrogate surrogate)
 {
     _surrogatesToBePersisted[surrogate.UniqueID] = surrogate;
 }
Example #16
0
 public void AddSurrogateHolder(StateObjectSurrogate value)
 {
     throw new NotImplementedException();
 }
Example #17
0
 private void AddSurrogateHolder(StateObjectSurrogate value)
 {
     _orphanHolders.Add(value);
 }
        internal static void DeserializeStateForDelegate(BinaryReader reader, Type delegateClassType, object instance, ref string fieldName, string prefix = null)
        {
            var formatter = new BinaryFormatter();
            var fieldList = delegateClassType.Fields(BindingFlags.Public | BindingFlags.Instance);

            foreach (var field in fieldList)
            {
                if (fieldName == null)
                {
                    if (reader.BaseStream.Position == reader.BaseStream.Length)
                    {/*No more data*/
                        return;
                    }
                    fieldName = reader.ReadString();
                    if (prefix != null)
                    {
                        if (fieldName.StartsWith(prefix, StringComparison.Ordinal))
                        {
                            fieldName = fieldName.Substring(prefix.Length);
                        }
                    }

                    TraceUtil.WriteLine(string.Format("Setting value for field {0}", fieldName));
                }
                //Skip until find matching field
                if (!fieldName.Equals(field.Name, StringComparison.Ordinal))
                {
                    continue;
                }

                if (field.Name.Contains("<>") && field.Name.Contains("locals"))
                {
                    //Is it in locals??
                    //Check if still goes here.
                    var surrogateUID    = reader.ReadString();
                    var localsSurrogate = (StateObjectSurrogate)StateManager.Current.GetObject(surrogateUID);
                    var localsInstance  = localsSurrogate.Value;
                    field.SetValue(instance, localsInstance);
                    fieldName = null;
                    continue;
                }
                //Is not locals.mmm ok is it an StateObject
                if (typeof(IStateObject).IsAssignableFrom(field.FieldType) ||
                    (field.FieldType.IsGenericType &&
                     (typeof(IList <>).IsAssignableFrom(field.FieldType.GetGenericTypeDefinition()) ||
                      typeof(IDictionary <,>).IsAssignableFrom(field.FieldType.GetGenericTypeDefinition()))
                    ))
                {
                    var uid = reader.ReadString();
                    if (!String.IsNullOrWhiteSpace(uid))
                    {
                        var fieldValue = StateManager.Current.GetObject(uid);
                        var surrogate  = fieldValue as StateObjectSurrogate;
                        if (surrogate != null)
                        {
                            fieldValue = surrogate.Value as IStateObject;
                        }
                        field.SetValue(instance, fieldValue);
                    }
                    fieldName = null;
                }
                else if (typeof(ILogicWithViewModel <IStateObject>).IsAssignableFrom(field.FieldType))
                {
                    fieldName = null;
                    var uid = reader.ReadString();
                    var vm  = StateManager.Current.GetObject(uid);
                    if (vm != null)
                    {
                        Type logicType = field.FieldType;
                        if (logicType.IsInterface)
                        {
                            var logicAttr = vm.GetType().GetCustomAttribute(typeof(UpgradeHelpers.Helpers.LogicAttribute)) as UpgradeHelpers.Helpers.LogicAttribute;
                            if (logicAttr == null)
                            {
                                throw new InvalidOperationException("The logic type for the viewmodel could not be determined. Please decorate the ViewModel class type with the Logic Attribute. for example [Logic(Type = typeof(LogicClass)]");
                            }
                            logicType = logicAttr.Type;
                        }

                        var form = IocContainerImplWithUnity.Current.Resolve(logicType, null, IIocContainerFlags.NoView | IIocContainerFlags.RecoveredFromStorage) as ILogicView <IViewModel>;
                        form.SetPropertyValue("ViewModel", vm);
                        field.SetValue(instance, form);
                    }
                    else
                    {
                        throw new InvalidOperationException(string.Format("The ViewModel for field {0} could not be restored ", field.Name));
                    }
                }
                else
                {
                    if (field.FieldType.IsSerializable && typeof(MulticastDelegate).IsAssignableFrom(field.FieldType))
                    {
                        RestoreDelegateField(reader, instance, field);
                    }
                    else if (SurrogatesDirectory.IsSurrogateRegistered(field.FieldType))
                    {
                        var uid = reader.ReadString();
                        if (!String.IsNullOrWhiteSpace(uid))
                        {
                            StateObjectSurrogate surrogate = StateManager.Current.surrogateManager.GetObject(uid);
                            field.SetValue(instance, surrogate.Value);
                        }
                    }
                    else if (field.FieldType.IsSerializable)
                    {
                        var fieldValue = formatter.Deserialize(reader.BaseStream);
                        field.SetValue(instance, fieldValue);
                    }
                    fieldName = null;
                }
            }
        }
Example #19
0
        /// <summary>
        /// Tries to recover an StateObject instance thru an StateObjectPointer
        /// </summary>
        /// <param name="input"></param>
        /// <param name="propEx"></param>
        /// <param name="parentInstance"></param>
        /// <param name="forSurrogate"></param>
        /// <param name="updateProperty"></param>
        /// <returns></returns>
        internal static object TryToRecoverWithPointer(StateManager stateManager, PropertyInfoEx propEx, IStateObject parentInstance, bool forSurrogate, bool updateProperty = true, StateObjectPointer pointer = null)
        {
            object cachedValue             = null;
            StateObjectSurrogate surrogate = null;

            if (pointer != null)
            {
                if (forSurrogate)
                {
                    surrogate   = (StateObjectSurrogate)pointer.Target;
                    cachedValue = surrogate.Value;
                }
                else
                {
                    var superValuePointer = pointer as StateObjectPointerReferenceSuperValueBase;
                    if (superValuePointer != null)
                    {
                        if (superValuePointer is StateObjectPointerReferenceSuperValue)
                        {
                            cachedValue = superValuePointer.SuperTarget;
                        }

                        else if (superValuePointer is StateObjectPointerReferenceSuperSurrogate)
                        {
                            cachedValue = (superValuePointer.SuperTarget as StateObjectSurrogate).Value;
                        }

                        else if (superValuePointer is StateObjectPointerReferenceSerializable)
                        {
                            cachedValue = superValuePointer.SuperTarget;
                        }

                        if (cachedValue == null)                         //Reference is pointing to nothing so lets get rid of it
                        {
                            stateManager.RemoveObject(pointer.UniqueID, true);
                        }
                    }
                    else
                    {
                        cachedValue = pointer.Target;
                        if (cachedValue == null)                         //Reference is pointing to nothing so lets get rid of it
                        {
                            stateManager.RemoveObject(pointer.UniqueID, true);
                        }
                        ///Added to support cases in that the referenced object is a Surrogate
                        else if (cachedValue is StateObjectSurrogate)
                        {
                            surrogate    = (StateObjectSurrogate)pointer.Target;
                            cachedValue  = surrogate.Value;
                            forSurrogate = true;
                        }
                    }
                }
                if (updateProperty)
                {
                    propEx.OriginalSetter(parentInstance, cachedValue);
                }
                if (forSurrogate)
                {
                    stateManager.AttachBindingBehaviourForSurrogate(surrogate, cachedValue);
                }
            }
            return(cachedValue);
        }
Example #20
0
        internal static void ProcessSetterSurrogate(PropertyInfoEx propEx, object parentObject, object newValueObject, bool isNew = false)
        {
            //TODO might do direct cast without as. That will be slightly faster
            var    parentInstance = parentObject as IStateObject;
            var    stateManager   = StateManager.Current;
            var    uuidgen        = stateManager.UniqueIDGenerator;
            string propName       = GetPropertyName(propEx);

            var relativeUid = UniqueIDGenerator.GetPointerRelativeUniqueID(parentInstance, propName);
            var pointer     = (StateObjectPointer)stateManager.GetObject(relativeUid, isNew: isNew);


            if (newValueObject == null)
            {
                //Here we need to remove the surrogate reference if available
                if (propEx.hasReferenceAttribute)
                {
                    //However we do no have yet implemented support for Surrogates along with references
                    throw new NotSupportedException();
                    //TODO
                }
                //If there was a value there was a pointer
                //Surrogates are always accessed thu a pointer
                if (pointer != null)
                {
                    //Retrieve surrogate
                    var surrogate = (StateObjectSurrogate)pointer.Target;
                    //Decrease surrogate references //If references drops to 0. Then remove surrogate
                    stateManager.surrogateManager.RemoveSurrogateReference(surrogate, pointer);
                    //Eliminate pointer
                    stateManager.RemoveObject(pointer.UniqueID, true);
                }
            }
            else
            {
                bool somethingToDo = true;
                //Was there a previous value? If there was one then there was a pointer.
                //If not we need one now.
                if (pointer == null)
                {
                    pointer = new StateObjectPointer();
                    AddDependent(parentInstance, UniqueIDGenerator.REFERENCEPrefix + GetPropertyName(propEx));
                    StateObjectPointer.AssignUniqueIdToPointer(parentInstance, relativeUid, pointer);
                }
                else
                {
                    //I need to validate that the surrogate is the same and if not decrease reference
                    //First lets see if this is same object
                    var oldsurrogate = (StateObjectSurrogate)pointer.Target;
                    if (oldsurrogate != null)
                    {
                        if (Object.ReferenceEquals(oldsurrogate.Value, newValueObject))
                        {
                            //Nothing to do
                            somethingToDo = false;
                        }
                        else
                        {
                            //Retrieve surrogate
                            StateObjectSurrogate surrogate = stateManager.surrogateManager.GetSurrogateFor(newValueObject, generateIfNotFound: true);
                            if (surrogate == null)
                            {
                                throw new Exception("Object must be instantiated/registered with resolve");
                            }
                            //Add reference if needed
                            stateManager.surrogateManager.AddSurrogateReference(surrogate, pointer, false);
                            stateManager.RebindSurrogateReference(oldsurrogate, surrogate, pointer);
                            somethingToDo = false;
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException("Pointer is broken. It should point to an existing surrogate");
                    }
                }

                if (somethingToDo)
                {
                    //Retrieve surrogate
                    StateObjectSurrogate surrogate = stateManager.surrogateManager.GetSurrogateFor(newValueObject, generateIfNotFound: true);
                    if (surrogate == null)
                    {
                        throw new Exception("Object must be instantiated/registered with resolve");
                    }
                    //Add reference if needed
                    stateManager.surrogateManager.AddSurrogateReference(surrogate, pointer, false);
                }
            }
        }
Example #21
0
 public void SendToSurrogatesToBePersisted(StateObjectSurrogate surrogate)
 {
     _surrogatesToBePersisted.Add(surrogate);
 }