Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
11/06/10 01:56:04 (14 years ago)
Author:
swagner
Message:

Merged cloning refactoring branch back into trunk (#922)

Location:
trunk/sources
Files:
25 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources

  • trunk/sources/HeuristicLab.Operators/3.3/AlgorithmOperator.cs

    r3376 r4722  
    4444    }
    4545
     46    [StorableConstructor]
     47    protected AlgorithmOperator(bool deserializing) : base(deserializing) { }
     48    protected AlgorithmOperator(AlgorithmOperator original, Cloner cloner)
     49      : base(original, cloner) {
     50      this.operatorGraph = cloner.Clone<OperatorGraph>(original.operatorGraph);
     51    }
    4652    protected AlgorithmOperator()
    4753      : base() {
    4854      operatorGraph = new OperatorGraph();
    49     }
    50 
    51     public override IDeepCloneable Clone(Cloner cloner) {
    52       AlgorithmOperator clone = (AlgorithmOperator)base.Clone(cloner);
    53       clone.operatorGraph = (OperatorGraph)cloner.Clone(operatorGraph);
    54       return clone;
    5555    }
    5656
  • trunk/sources/HeuristicLab.Operators/3.3/Assigner.cs

    r4068 r4722  
    2020#endregion
    2121
     22using HeuristicLab.Common;
    2223using HeuristicLab.Core;
    2324using HeuristicLab.Parameters;
     
    3839    }
    3940
     41    [StorableConstructor]
     42    private Assigner(bool deserializing) : base(deserializing) { }
     43    private Assigner(Assigner original, Cloner cloner)
     44      : base(original, cloner) {
     45    }
    4046    public Assigner()
    4147      : base() {
    4248      Parameters.Add(new LookupParameter<IItem>("LeftSide", "The parameter whose value gets assigned with a clone of the other parameter's value."));
    4349      Parameters.Add(new ValueLookupParameter<IItem>("RightSide", "The parameter whose value is cloned and assigned to the value of the other parameter."));
     50    }
     51
     52    public override IDeepCloneable Clone(Cloner cloner) {
     53      return new Assigner(this, cloner);
    4454    }
    4555
  • trunk/sources/HeuristicLab.Operators/3.3/CheckedMultiOperator.cs

    r4068 r4722  
    2020#endregion
    2121
     22using HeuristicLab.Common;
    2223using HeuristicLab.Core;
    2324using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
     
    3738      protected set { base.Operators = value; }
    3839    }
     40
     41    [StorableConstructor]
     42    protected CheckedMultiOperator(bool deserializing) : base(deserializing) { }
     43    protected CheckedMultiOperator(CheckedMultiOperator<T> original, Cloner cloner)
     44      : base(original, cloner) {
     45    }
    3946    /// <summary>
    4047    /// Creates a new instance of CheckedMultiOperator
     
    4451      Operators = new CheckedItemList<T>();
    4552    }
    46     [StorableConstructor]
    47     protected CheckedMultiOperator(bool deserializing) : base(deserializing) { }
    4853  }
    4954}
  • trunk/sources/HeuristicLab.Operators/3.3/CombinedOperator.cs

    r4477 r4722  
    4343    }
    4444
     45    [StorableConstructor]
     46    private CombinedOperator(bool deserializing) : base(deserializing) { }
     47    private CombinedOperator(CombinedOperator original, Cloner cloner)
     48      : base(original, cloner) {
     49    }
    4550    public CombinedOperator() : base() { }
     51
     52    public override IDeepCloneable Clone(Cloner cloner) {
     53      return new CombinedOperator(this, cloner);
     54    }
    4655  }
    4756}
  • trunk/sources/HeuristicLab.Operators/3.3/Comparator.cs

    r4068 r4722  
    2121
    2222using System;
     23using HeuristicLab.Common;
    2324using HeuristicLab.Core;
    2425using HeuristicLab.Data;
     
    5051    }
    5152
     53    [StorableConstructor]
     54    private Comparator(bool deserializing) : base(deserializing) { }
     55    private Comparator(Comparator original, Cloner cloner)
     56      : base(original, cloner) {
     57    }
    5258    public Comparator()
    5359      : base() {
     
    5662      Parameters.Add(new ValueParameter<Comparison>("Comparison", "The type of comparison.", new Comparison(Data.ComparisonType.Equal)));
    5763      Parameters.Add(new LookupParameter<BoolValue>("Result", "The result of the comparison."));
     64    }
     65
     66    public override IDeepCloneable Clone(Cloner cloner) {
     67      return new Comparator(this, cloner);
    5868    }
    5969
  • trunk/sources/HeuristicLab.Operators/3.3/ConditionalBranch.cs

    r4477 r4722  
    2020#endregion
    2121
     22using HeuristicLab.Common;
    2223using HeuristicLab.Core;
    2324using HeuristicLab.Data;
     
    5051    }
    5152
     53    [StorableConstructor]
     54    protected ConditionalBranch(bool deserializing) : base(deserializing) { }
     55    protected ConditionalBranch(ConditionalBranch original, Cloner cloner)
     56      : base(original, cloner) {
     57    }
    5258    public ConditionalBranch()
    5359      : base() {
     
    5561      Parameters.Add(new OperatorParameter("TrueBranch", "The operator which is executed if the condition is true."));
    5662      Parameters.Add(new OperatorParameter("FalseBranch", "The operator which is executed if the condition is false."));
     63    }
     64
     65    public override IDeepCloneable Clone(Cloner cloner) {
     66      return new ConditionalBranch(this, cloner);
    5767    }
    5868
  • trunk/sources/HeuristicLab.Operators/3.3/DoubleCounter.cs

    r4477 r4722  
    2020#endregion
    2121
     22using HeuristicLab.Common;
    2223using HeuristicLab.Core;
    2324using HeuristicLab.Data;
     
    4344    }
    4445
     46    [StorableConstructor]
     47    private DoubleCounter(bool deserializing) : base(deserializing) { }
     48    private DoubleCounter(DoubleCounter original, Cloner cloner)
     49      : base(original, cloner) {
     50    }
    4551    public DoubleCounter()
    4652      : base() {
    4753      Parameters.Add(new LookupParameter<DoubleValue>("Value", "The value which should be incremented."));
    4854      Parameters.Add(new ValueLookupParameter<DoubleValue>("Increment", "The increment which is added to the value.", new DoubleValue(1)));
     55    }
     56
     57    public override IDeepCloneable Clone(Cloner cloner) {
     58      return new DoubleCounter(this, cloner);
    4959    }
    5060
  • trunk/sources/HeuristicLab.Operators/3.3/EmptyOperator.cs

    r4477 r4722  
    2020#endregion
    2121
     22using HeuristicLab.Common;
    2223using HeuristicLab.Core;
    2324using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
     
    3031  [StorableClass]
    3132  public sealed class EmptyOperator : SingleSuccessorOperator {
     33    [StorableConstructor]
     34    private EmptyOperator(bool deserializing) : base(deserializing) { }
     35    private EmptyOperator(EmptyOperator original, Cloner cloner)
     36      : base(original, cloner) {
     37    }
    3238    public EmptyOperator()
    3339      : base() {
    3440    }
     41
     42    public override IDeepCloneable Clone(Cloner cloner) {
     43      return new EmptyOperator(this, cloner);
     44    }
    3545  }
    3646}
  • trunk/sources/HeuristicLab.Operators/3.3/IntCounter.cs

    r4477 r4722  
    2020#endregion
    2121
     22using HeuristicLab.Common;
    2223using HeuristicLab.Core;
    2324using HeuristicLab.Data;
     
    4344    }
    4445
     46    [StorableConstructor]
     47    private IntCounter(bool deserializing) : base(deserializing) { }
     48    private IntCounter(IntCounter original, Cloner cloner)
     49      : base(original, cloner) {
     50    }
    4551    public IntCounter()
    4652      : base() {
    4753      Parameters.Add(new LookupParameter<IntValue>("Value", "The value which should be incremented."));
    4854      Parameters.Add(new ValueLookupParameter<IntValue>("Increment", "The increment which is added to the value.", new IntValue(1)));
     55    }
     56
     57    public override IDeepCloneable Clone(Cloner cloner) {
     58      return new IntCounter(this, cloner);
    4959    }
    5060
  • trunk/sources/HeuristicLab.Operators/3.3/MultiOperator.cs

    r4068 r4722  
    5151    }
    5252
     53    [StorableConstructor]
     54    protected MultiOperator(bool deserializing) : base(deserializing) { }
     55    protected MultiOperator(MultiOperator<T> original, Cloner cloner)
     56      : base(original, cloner) {
     57      this.operators = cloner.Clone<IItemList<T>>(original.operators);
     58      Initialize();
     59    }
    5360    public MultiOperator()
    5461      : base() {
     
    5764    }
    5865
    59     [StorableConstructor]
    60     protected MultiOperator(bool deserializing) : base(deserializing) { }
    61 
    6266    [StorableHook(HookType.AfterDeserialization)]
     67    private void AfterDeserialization() {
     68      Initialize();
     69    }
     70   
    6371    private void Initialize() {
    6472      if (operators != null) RegisterOperatorsEvents();
     
    6977        opParam.ValueChanged += new EventHandler(opParam_ValueChanged);
    7078      }
    71     }
    72 
    73     public override IDeepCloneable Clone(Cloner cloner) {
    74       MultiOperator<T> clone = (MultiOperator<T>)base.Clone(cloner);
    75       clone.operators = (IItemList<T>)cloner.Clone(operators);
    76       clone.Initialize();
    77       return clone;
    7879    }
    7980
  • trunk/sources/HeuristicLab.Operators/3.3/Operator.cs

    r4477 r4722  
    8585    }
    8686
     87    [StorableConstructor]
     88    protected Operator(bool deserializing) : base(deserializing) { }
     89    protected Operator(Operator original, Cloner cloner)
     90      : base(original, cloner) {
     91      this.canceled = original.canceled;
     92      this.breakpoint = original.breakpoint;
     93      this.executionContext = cloner.Clone<IExecutionContext>(original.executionContext);
     94    }
    8795    /// <summary>
    8896    /// Initializes a new instance of <see cref="OperatorBase"/> setting the breakpoint flag and
     
    113121      canceled = false;
    114122      breakpoint = false;
    115     }
    116     [StorableConstructor]
    117     protected Operator(bool deserializing) : base(deserializing) { }
    118 
    119     /// <summary>
    120     /// Clones the current instance (deep clone).
    121     /// </summary>
    122     /// <remarks>Clones also sub operators, variables and variable infos.</remarks>
    123     /// <param name="clonedObjects">Dictionary of all already cloned objects. (Needed to avoid cycles.)</param>
    124     /// <returns>The cloned object as <see cref="OperatorBase"/>.</returns>
    125     public override IDeepCloneable Clone(Cloner cloner) {
    126       Operator clone = (Operator)base.Clone(cloner);
    127       clone.canceled = canceled;
    128       clone.breakpoint = breakpoint;
    129       clone.executionContext = (IExecutionContext)cloner.Clone(executionContext);
    130       return clone;
    131123    }
    132124
  • trunk/sources/HeuristicLab.Operators/3.3/Placeholder.cs

    r4477 r4722  
    2020#endregion
    2121
     22using HeuristicLab.Common;
    2223using HeuristicLab.Core;
    2324using HeuristicLab.Parameters;
     
    3536    }
    3637
     38    [StorableConstructor]
     39    private Placeholder(bool deserializing) : base(deserializing) { }
     40    private Placeholder(Placeholder original, Cloner cloner)
     41      : base(original, cloner) {
     42    }
    3743    public Placeholder()
    3844      : base() {
    3945      Parameters.Add(new LookupParameter<IOperator>("Operator", "The operator which is retrieved from the scope or a parent execution context and applied on the current scope."));
     46    }
     47
     48    public override IDeepCloneable Clone(Cloner cloner) {
     49      return new Placeholder(this, cloner);
    4050    }
    4151
  • trunk/sources/HeuristicLab.Operators/3.3/ScopeCleaner.cs

    r4477 r4722  
    2020#endregion
    2121
     22using HeuristicLab.Common;
    2223using HeuristicLab.Core;
    2324using HeuristicLab.Parameters;
     
    3839    }
    3940
     41    [StorableConstructor]
     42    private ScopeCleaner(bool deserializing) : base(deserializing) { }
     43    private ScopeCleaner(ScopeCleaner original, Cloner cloner)
     44      : base(original, cloner) {
     45    }
    4046    public ScopeCleaner()
    4147      : base() {
    4248      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope whose variables and sub-scopes should be removed."));
     49    }
     50
     51    public override IDeepCloneable Clone(Cloner cloner) {
     52      return new ScopeCleaner(this, cloner);
    4353    }
    4454
  • trunk/sources/HeuristicLab.Operators/3.3/SingleSuccessorOperator.cs

    r4477 r4722  
    2020#endregion
    2121
     22using HeuristicLab.Common;
    2223using HeuristicLab.Core;
    2324using HeuristicLab.Parameters;
     
    3940    }
    4041
     42    [StorableConstructor]
     43    protected SingleSuccessorOperator(bool deserializing) : base(deserializing) { }
     44    protected SingleSuccessorOperator(SingleSuccessorOperator original, Cloner cloner)
     45      : base(original, cloner) {
     46    }
    4147    public SingleSuccessorOperator()
    4248      : base() {
    4349      Parameters.Add(new OperatorParameter("Successor", "Operator which is executed next."));
    4450    }
    45     [StorableConstructor]
    46     protected SingleSuccessorOperator(bool deserializing) : base(deserializing) { }
    47 
     51   
    4852    public override IOperation Apply() {
    4953      if (Successor != null)
  • trunk/sources/HeuristicLab.Operators/3.3/StochasticBranch.cs

    r4477 r4722  
    2020#endregion
    2121
     22using HeuristicLab.Common;
    2223using HeuristicLab.Core;
    2324using HeuristicLab.Data;
     
    5354    }
    5455
     56    [StorableConstructor]
     57    protected StochasticBranch(bool deserializing) : base(deserializing) { }
     58    protected StochasticBranch(StochasticBranch original, Cloner cloner)
     59      : base(original, cloner) {
     60    }
    5561    public StochasticBranch()
    5662      : base() {
     
    5965      Parameters.Add(new OperatorParameter("FirstBranch", "The operator which is executed with the given probability."));
    6066      Parameters.Add(new OperatorParameter("SecondBranch", "The operator which is executed if the first branch is not executed."));
     67    }
     68
     69    public override IDeepCloneable Clone(Cloner cloner) {
     70      return new StochasticBranch(this, cloner);
    6171    }
    6272
  • trunk/sources/HeuristicLab.Operators/3.3/StochasticMultiBranch.cs

    r4477 r4722  
    2424using System.Linq;
    2525using HeuristicLab.Collections;
     26using HeuristicLab.Common;
    2627using HeuristicLab.Core;
    2728using HeuristicLab.Data;
     
    5657    [StorableConstructor]
    5758    protected StochasticMultiBranch(bool deserializing) : base(deserializing) { }
     59    protected StochasticMultiBranch(StochasticMultiBranch<T> original, Cloner cloner)
     60      : base(original, cloner) {
     61    }
    5862    /// <summary>
    5963    /// Initializes a new instance of <see cref="StochasticMultiOperator"/> with two parameters
     
    143147  [StorableClass]
    144148  public class StochasticMultiBranch : StochasticMultiBranch<IOperator> {
     149    [StorableConstructor]
     150    protected StochasticMultiBranch(bool deserializing) : base(deserializing) { }
     151    protected StochasticMultiBranch(StochasticMultiBranch original, Cloner cloner)
     152      : base(original, cloner) {
     153    }
     154    public StochasticMultiBranch() { }
     155
     156    public override IDeepCloneable Clone(Cloner cloner) {
     157      return new StochasticMultiBranch(this, cloner);
     158    }
     159
    145160    protected override bool CreateChildOperation {
    146161      get { return false; }
  • trunk/sources/HeuristicLab.Operators/3.3/SubScopesCreator.cs

    r4477 r4722  
    2020#endregion
    2121
     22using HeuristicLab.Common;
    2223using HeuristicLab.Core;
    2324using HeuristicLab.Data;
     
    4243    }
    4344
     45    [StorableConstructor]
     46    protected SubScopesCreator(bool deserializing) : base(deserializing) { }
     47    protected SubScopesCreator(SubScopesCreator original, Cloner cloner)
     48      : base(original, cloner) {
     49    }
    4450    public SubScopesCreator()
    4551      : base() {
    4652      Parameters.Add(new ValueLookupParameter<IntValue>("NumberOfSubScopes", "The number of new and empty sub-scopes which should be added to the current scope."));
    4753      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope to which the new and empty sub-scopes are added."));
     54    }
     55
     56    public override IDeepCloneable Clone(Cloner cloner) {
     57      return new SubScopesCreator(this, cloner);
    4858    }
    4959
  • trunk/sources/HeuristicLab.Operators/3.3/SubScopesMixer.cs

    r4477 r4722  
    2121
    2222using System;
     23using HeuristicLab.Common;
    2324using HeuristicLab.Core;
    2425using HeuristicLab.Data;
     
    4243    }
    4344
     45    [StorableConstructor]
     46    protected SubScopesMixer(bool deserializing) : base(deserializing) { }
     47    protected SubScopesMixer(SubScopesMixer original, Cloner cloner)
     48      : base(original, cloner) {
     49    }
    4450    /// <summary>
    4551    /// Initializes a new instance of <see cref="SubScopesMixer"/> with one variable infos
     
    4955      : base() {
    5056      Parameters.Add(new ValueParameter<IntValue>("Partitions", "The number of equal-sized partitions.", new IntValue(2)));
     57    }
     58
     59    public override IDeepCloneable Clone(Cloner cloner) {
     60      return new SubScopesMixer(this, cloner);
    5161    }
    5262
  • trunk/sources/HeuristicLab.Operators/3.3/SubScopesProcessor.cs

    r4477 r4722  
    2323using System.Collections.Generic;
    2424using System.Linq;
     25using HeuristicLab.Common;
    2526using HeuristicLab.Core;
    2627using HeuristicLab.Data;
     
    5152    }
    5253
     54    [StorableConstructor]
     55    private SubScopesProcessor(bool deserializing) : base(deserializing) { }
     56    private SubScopesProcessor(SubScopesProcessor original, Cloner cloner)
     57      : base(original, cloner) {
     58    }
    5359    public SubScopesProcessor()
    5460      : base() {
    5561      Parameters.Add(new ValueLookupParameter<BoolValue>("Parallel", "True if the operators should be applied in parallel on the sub-scopes, otherwise false.", new BoolValue(false)));
    5662      Parameters.Add(new ValueParameter<IntValue>("Depth", "The number of steps to descend in the scope tree before applying operator.", new IntValue(1)));
     63    }
     64
     65    public override IDeepCloneable Clone(Cloner cloner) {
     66      return new SubScopesProcessor(this, cloner);
    5767    }
    5868
  • trunk/sources/HeuristicLab.Operators/3.3/SubScopesRemover.cs

    r4477 r4722  
    2020#endregion
    2121
     22using HeuristicLab.Common;
    2223using HeuristicLab.Core;
    2324using HeuristicLab.Data;
     
    5051    }
    5152
     53    [StorableConstructor]
     54    private SubScopesRemover(bool deserializing) : base(deserializing) { }
     55    private SubScopesRemover(SubScopesRemover original, Cloner cloner)
     56      : base(original, cloner) {
     57    }
    5258    public SubScopesRemover()
    5359      : base() {
     
    5561      Parameters.Add(new ValueLookupParameter<IntValue>("SubScopeIndex", "The index of the sub-scope which should be removed. This parameter is ignored, if RemoveAllSubScopes is true."));
    5662      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope from which one or all sub-scopes should be removed."));
     63    }
     64
     65    public override IDeepCloneable Clone(Cloner cloner) {
     66      return new SubScopesRemover(this, cloner);
    5767    }
    5868
  • trunk/sources/HeuristicLab.Operators/3.3/SubScopesSorter.cs

    r4068 r4722  
    2020#endregion
    2121
     22using HeuristicLab.Common;
    2223using HeuristicLab.Core;
    2324using HeuristicLab.Data;
     
    4849    }
    4950
     51    [StorableConstructor]
     52    private SubScopesSorter(bool deserializing) : base(deserializing) { }
     53    private SubScopesSorter(SubScopesSorter original, Cloner cloner)
     54      : base(original, cloner) {
     55    }
    5056    public SubScopesSorter()
    5157      : base() {
     
    5359      Parameters.Add(new ValueLookupParameter<BoolValue>("Descending", "True if the sub-scopes should be sorted in descending order, otherwise false."));
    5460      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope whose sub-scopes are sorted."));
     61    }
     62
     63    public override IDeepCloneable Clone(Cloner cloner) {
     64      return new SubScopesSorter(this, cloner);
    5565    }
    5666
  • trunk/sources/HeuristicLab.Operators/3.3/UniformSubScopesProcessor.cs

    r4477 r4722  
    2222using System.Collections.Generic;
    2323using System.Linq;
     24using HeuristicLab.Common;
    2425using HeuristicLab.Core;
    2526using HeuristicLab.Data;
     
    5758    }
    5859
     60    [StorableConstructor]
     61    private UniformSubScopesProcessor(bool deserializing) : base(deserializing) { }
     62    private UniformSubScopesProcessor(UniformSubScopesProcessor original, Cloner cloner)
     63      : base(original, cloner) {
     64    }
    5965    public UniformSubScopesProcessor()
    6066      : base() {
     
    6268      Parameters.Add(new ValueLookupParameter<BoolValue>("Parallel", "True if the operator should be applied in parallel on all sub-scopes, otherwise false.", new BoolValue(false)));
    6369      Parameters.Add(new ValueParameter<IntValue>("Depth", "The number of steps to descend in the scope tree before applying operator.", new IntValue(1)));
     70    }
     71
     72    public override IDeepCloneable Clone(Cloner cloner) {
     73      return new UniformSubScopesProcessor(this, cloner);
    6474    }
    6575
  • trunk/sources/HeuristicLab.Operators/3.3/ValuesCollector.cs

    r3376 r4722  
    3838    }
    3939
     40    [StorableConstructor]
     41    protected ValuesCollector(bool deserializing) : base(deserializing) { }
     42    protected ValuesCollector(ValuesCollector original, Cloner cloner)
     43      : base(original, cloner) {
     44      this.collectedValues = cloner.Clone<ParameterCollection>(original.collectedValues);
     45      Initialize();
     46    }
    4047    public ValuesCollector()
    4148      : base() {
     
    4350      Initialize();
    4451    }
    45     [StorableConstructor]
    46     protected ValuesCollector(bool deserializing) : base(deserializing) { }
    4752
    4853    [StorableHook(HookType.AfterDeserialization)]
     54    private void AfterDeserialization() {
     55      Initialize();
     56    }
     57
    4958    private void Initialize() {
    5059      collectedValues.ItemsAdded += new CollectionItemsChangedEventHandler<IParameter>(collectedValues_ItemsAdded);
    5160      collectedValues.ItemsRemoved += new CollectionItemsChangedEventHandler<IParameter>(collectedValues_ItemsRemoved);
    5261      collectedValues.CollectionReset += new CollectionItemsChangedEventHandler<IParameter>(collectedValues_CollectionReset);
    53     }
    54 
    55     public override IDeepCloneable Clone(Cloner cloner) {
    56       ValuesCollector clone = (ValuesCollector)base.Clone(cloner);
    57       clone.collectedValues = (ParameterCollection)cloner.Clone(collectedValues);
    58       clone.Initialize();
    59       return clone;
    6062    }
    6163
  • trunk/sources/HeuristicLab.Operators/3.3/VariableCreator.cs

    r4477 r4722  
    2020#endregion
    2121
     22using HeuristicLab.Common;
    2223using HeuristicLab.Core;
    2324using HeuristicLab.Parameters;
     
    3839    }
    3940
     41    [StorableConstructor]
     42    protected VariableCreator(bool deserializing) : base(deserializing) { }
     43    protected VariableCreator(VariableCreator original, Cloner cloner)
     44      : base(original, cloner) {
     45    }
    4046    public VariableCreator()
    4147      : base() {
    4248      Parameters.Add(new ScopeParameter("CurrentScope", "The current scope into which the parameter values are cloned."));
     49    }
     50
     51    public override IDeepCloneable Clone(Cloner cloner) {
     52      return new VariableCreator(this, cloner);
    4353    }
    4454
Note: See TracChangeset for help on using the changeset viewer.