1+ // Copyright (C) 2009-2025 Xtensive LLC.
2+ // This code is distributed under MIT license terms.
3+ // See the License.txt file in the project root for more information.
4+ // Created by: Ivan Galkin
5+ // Created: 2009.05.20
6+
7+ using System ;
8+ using System . Collections . Generic ;
9+ using Xtensive . Core ;
10+ using Xtensive . Orm . Upgrade ;
11+ using Xtensive . Orm . Tests . Upgrade . Models . Version2 ;
12+
13+ namespace Xtensive . Orm . Tests . Upgrade . Models
14+ {
15+ [ Serializable ]
16+ public class Upgrader : UpgradeHandler
17+ {
18+ [ Flags ]
19+ public enum ModelParts
20+ {
21+ Order = 1 << 0 ,
22+ Product = 1 << 1 ,
23+ BoyGirl = 1 << 2 ,
24+ CrazyAssociations = 1 << 3 ,
25+ ComplexFieldCopy = 1 << 4 ,
26+ Generics = Order | BoyGirl | 1 << 5 ,
27+ All = Order | Product | BoyGirl | CrazyAssociations | ComplexFieldCopy | Generics
28+ }
29+
30+ private const string Version1Ns = "Xtensive.Orm.Tests.Upgrade.Models.Version1" ;
31+
32+ private static bool isEnabled = false ;
33+ private static int ? runningVersion ;
34+ private static ModelParts modelParts = ModelParts . All ;
35+
36+ /// <exception cref="InvalidOperationException">Handler is already enabled.</exception>
37+ public static IDisposable EnableForVersion ( int version )
38+ {
39+ if ( isEnabled )
40+ throw new InvalidOperationException ( ) ;
41+ isEnabled = true ;
42+ runningVersion = version ;
43+ return new Disposable ( _ => {
44+ isEnabled = false ;
45+ runningVersion = null ;
46+ } ) ;
47+ }
48+
49+ /// <exception cref="InvalidOperationException">Handler is already enabled.</exception>
50+ public static IDisposable EnableForVersion ( int version , ModelParts parts )
51+ {
52+ if ( isEnabled )
53+ throw new InvalidOperationException ( ) ;
54+ isEnabled = true ;
55+ runningVersion = version ;
56+ modelParts = parts ;
57+ return new Disposable ( _ => {
58+ isEnabled = false ;
59+ runningVersion = null ;
60+ modelParts = ModelParts . All ;
61+ } ) ;
62+ }
63+
64+
65+ public override bool IsEnabled => isEnabled ;
66+
67+ protected override string DetectAssemblyVersion ( ) => runningVersion . ToString ( ) ;
68+
69+ public override bool CanUpgradeFrom ( string oldVersion ) => true ;
70+
71+ protected override void AddUpgradeHints ( Collections . ISet < UpgradeHint > hints )
72+ {
73+ if ( runningVersion == 2 )
74+ Version1To2Hints . ForEach ( hint => hints . Add ( hint ) ) ;
75+ if ( runningVersion == 3 )
76+ Version1To3Hints . ForEach ( hint => hints . Add ( hint ) ) ;
77+ }
78+
79+ public override void OnUpgrade ( )
80+ {
81+ }
82+
83+ public override bool IsTypeAvailable ( Type type , UpgradeStage upgradeStage )
84+ {
85+ string suffix = $ ".Version{ runningVersion } ";
86+ var originalNamespace = type . Namespace ;
87+ var nameSpace = originalNamespace . TryCutSuffix ( suffix ) ;
88+ return nameSpace != originalNamespace
89+ && base . IsTypeAvailable ( type , upgradeStage ) ;
90+ }
91+
92+ private static IEnumerable < UpgradeHint > Version1To2Hints
93+ {
94+ get {
95+ // renaming types
96+ if ( modelParts . HasFlag ( ModelParts . Order ) ) {
97+ yield return new RenameTypeHint (
98+ $ "{ Version1Ns } .BusinessContact", typeof ( Person ) ) ;
99+ yield return new RenameTypeHint (
100+ $ "{ Version1Ns } .Person", typeof ( BusinessContact ) ) ;
101+ yield return new RenameTypeHint (
102+ $ "{ Version1Ns } .Address", typeof ( Address ) ) ;
103+ yield return new RenameTypeHint (
104+ $ "{ Version1Ns } .Employee", typeof ( Employee ) ) ;
105+ yield return new RenameTypeHint (
106+ $ "{ Version1Ns } .Order", typeof ( Order ) ) ;
107+ }
108+
109+ if ( modelParts . HasFlag ( ModelParts . Product ) ) {
110+ yield return new RenameTypeHint (
111+ $ "{ Version1Ns } .Product", typeof ( Product ) ) ;
112+ yield return new RenameTypeHint (
113+ $ "{ Version1Ns } .Category", typeof ( ProductGroup ) ) ;
114+ }
115+
116+ if ( modelParts . HasFlag ( ModelParts . BoyGirl ) ) {
117+ yield return new RenameTypeHint (
118+ $ "{ Version1Ns } .Boy", typeof ( Boy ) ) ;
119+ yield return new RenameTypeHint (
120+ $ "{ Version1Ns } .Girl", typeof ( Girl ) ) ;
121+ }
122+
123+ if ( modelParts . HasFlag ( ModelParts . CrazyAssociations ) ) {
124+ yield return new RenameTypeHint (
125+ $ "{ Version1Ns } .Entity1", typeof ( Entity1 ) ) ;
126+ yield return new RenameTypeHint (
127+ $ "{ Version1Ns } .Entity2", typeof ( Entity2 ) ) ;
128+ yield return new RenameTypeHint (
129+ $ "{ Version1Ns } .Entity3", typeof ( Entity3 ) ) ;
130+ yield return new RenameTypeHint (
131+ $ "{ Version1Ns } .Entity4", typeof ( Entity4 ) ) ;
132+
133+ yield return new RenameTypeHint (
134+ $ "{ Version1Ns } .Structure1", typeof ( Structure1 ) ) ;
135+ yield return new RenameTypeHint (
136+ $ "{ Version1Ns } .Structure2", typeof ( Structure2 ) ) ;
137+ yield return new RenameTypeHint (
138+ $ "{ Version1Ns } .Structure3", typeof ( Structure3 ) ) ;
139+ yield return new RenameTypeHint (
140+ $ "{ Version1Ns } .Structure4", typeof ( Structure4 ) ) ;
141+
142+ yield return new RenameTypeHint (
143+ $ "{ Version1Ns } .StructureContainer1", typeof ( StructureContainer1 ) ) ;
144+ yield return new RenameTypeHint (
145+ $ "{ Version1Ns } .StructureContainer2", typeof ( StructureContainer2 ) ) ;
146+ yield return new RenameTypeHint (
147+ $ "{ Version1Ns } .StructureContainer3", typeof ( StructureContainer3 ) ) ;
148+ yield return new RenameTypeHint (
149+ $ "{ Version1Ns } .StructureContainer4", typeof ( StructureContainer4 ) ) ;
150+ }
151+
152+ if ( modelParts . HasFlag ( ModelParts . ComplexFieldCopy ) ) {
153+ yield return new RenameTypeHint (
154+ $ "{ Version1Ns } .MyStructureOwner", typeof ( MyStructureOwner ) ) ;
155+ yield return new RenameTypeHint (
156+ $ "{ Version1Ns } .ReferencedEntity", typeof ( ReferencedEntity ) ) ;
157+ }
158+
159+ if ( modelParts . HasFlag ( ModelParts . Generics ) ) {
160+ yield return new RenameTypeHint (
161+ $ "{ Version1Ns } .Sync<>", typeof ( NewSync < > ) ) ;
162+ }
163+
164+ // renaming fields
165+ if ( modelParts . HasFlag ( ModelParts . Order ) ) {
166+ yield return new RenameFieldHint ( typeof ( Order ) , "OrderNumber" , "Number" ) ;
167+ }
168+
169+ if ( modelParts . HasFlag ( ModelParts . Product ) ) {
170+ yield return new RenameFieldHint ( typeof ( Product ) , "Name" , "Title" ) ;
171+ yield return new RenameFieldHint ( typeof ( Product ) , "Category" , "Group" ) ;
172+ yield return new RenameFieldHint ( typeof ( ProductGroup ) , "Id" , "GroupId" ) ;
173+ }
174+
175+ if ( modelParts . HasFlag ( ModelParts . BoyGirl ) ) {
176+ yield return new RenameFieldHint ( typeof ( Boy ) , "FriendlyGirls" , "MeetWith" ) ;
177+ yield return new RenameFieldHint ( typeof ( Girl ) , "FriendlyBoys" , "MeetWith" ) ;
178+ }
179+
180+ if ( modelParts . HasFlag ( ModelParts . CrazyAssociations ) ) {
181+ yield return new RenameFieldHint ( typeof ( Entity1 ) , "Id" , "Code" ) ;
182+ yield return new RenameFieldHint ( typeof ( Entity2 ) , "Id" , "Code" ) ;
183+ yield return new RenameFieldHint ( typeof ( Entity3 ) , "Id" , "Code" ) ;
184+ yield return new RenameFieldHint ( typeof ( Entity4 ) , "Id" , "Code" ) ;
185+ yield return new RenameFieldHint ( typeof ( Structure1 ) , "E1" , "MyE1" ) ;
186+ yield return new RenameFieldHint ( typeof ( Structure2 ) , "E2" , "MyE2" ) ;
187+ yield return new RenameFieldHint ( typeof ( Structure3 ) , "E3" , "MyE3" ) ;
188+ yield return new RenameFieldHint ( typeof ( Structure4 ) , "E4" , "MyE4" ) ;
189+ }
190+
191+ if ( modelParts . HasFlag ( ModelParts . Generics ) ) {
192+ yield return new RenameFieldHint ( typeof ( NewSync < > ) , "Root" , "NewRoot" ) ;
193+ }
194+
195+ // type changes
196+ if ( modelParts . HasFlag ( ModelParts . Order ) ) {
197+ yield return new ChangeFieldTypeHint ( typeof ( Person ) , "PassportNumber" ) ;
198+ yield return new ChangeFieldTypeHint ( typeof ( Order ) , "Number" ) ;
199+ }
200+
201+ // copying data
202+ if ( modelParts . HasFlag ( ModelParts . Order ) ) {
203+ yield return new CopyFieldHint (
204+ $ "{ Version1Ns } .Employee", "FirstName" , typeof ( BusinessContact ) ) ;
205+ yield return new CopyFieldHint (
206+ $ "{ Version1Ns } .Employee", "LastName" , typeof ( BusinessContact ) ) ;
207+ }
208+ if ( ! IncludeTypeIdModifier . IsEnabled && modelParts . HasFlag ( ModelParts . ComplexFieldCopy ) )
209+ yield return new CopyFieldHint (
210+ $ "{ Version1Ns } .MyStructureOwner", "Structure" , typeof ( MyStructureOwner ) , "Reference" ) ;
211+
212+ }
213+ }
214+
215+ private IEnumerable < UpgradeHint > Version1To3Hints
216+ {
217+ get {
218+ yield return new RenameTypeHint (
219+ $ "{ Version1Ns } .Order", typeof ( Models . Version3 . Order ) ) ;
220+ yield return new RenameTypeHint (
221+ $ "{ Version1Ns } .Person", typeof ( Models . Version3 . Person ) ) ;
222+ }
223+ }
224+ }
225+ }
0 commit comments