1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle
.ActiveRecord
.Generator
.Components
18 using System
.Collections
;
20 using Castle
.ActiveRecord
.Generator
.Components
.Database
;
23 public class RelationshipInferenceService
: IRelationshipInferenceService
25 private INamingService _namingService
;
27 public RelationshipInferenceService(INamingService namingService
)
29 _namingService
= namingService
;
32 #region IRelationShipInferenceService Members
34 public ActiveRecordPropertyRelationDescriptor
[] InferRelations(ActiveRecordDescriptor desc
,
35 TableDefinition tableDef
, BuildContext context
)
37 if (desc
== null) throw new ArgumentNullException("desc");
38 if (tableDef
== null) throw new ArgumentNullException("tableDef");
39 if (context
== null) throw new ArgumentNullException("context");
40 // if (tableDef.RelatedDescriptor != null && tableDef.RelatedDescriptor != desc) {
41 // throw new ArgumentException("Different descriptors");
44 ArrayList list
= new ArrayList();
46 CreateHasManyRelations(desc
, tableDef
, list
, context
);
48 CreateBelongsToRelations(desc
, tableDef
, list
, context
);
50 return (ActiveRecordPropertyRelationDescriptor
[]) list
.ToArray( typeof(ActiveRecordPropertyRelationDescriptor
) );
53 private void CreateBelongsToRelations(ActiveRecordDescriptor desc
, TableDefinition tableDef
,
54 IList list
, BuildContext context
)
56 foreach(ColumnDefinition col
in tableDef
.Columns
)
58 if (col
.RelatedTable
!= null)
60 bool pendentNecessary
= false;
61 String propertyName
= _namingService
.CreateClassName(col
.RelatedTable
.Name
);
63 ActiveRecordDescriptor targetType
= null;
65 if (col
.RelatedTable
.RelatedDescriptor
== null && col
.RelatedTable
!= tableDef
)
67 col
.RelatedTable
.RelatedDescriptor
= new ActiveRecordDescriptor(col
.RelatedTable
);
69 pendentNecessary
= true;
71 else if (col
.RelatedTable
== tableDef
)
76 if (targetType
== null)
78 targetType
= col
.RelatedTable
.RelatedDescriptor
;
81 ActiveRecordBelongsToDescriptor belongsTo
=
82 new ActiveRecordBelongsToDescriptor(col
.Name
,
83 propertyName
, targetType
);
89 context
.AddPendentDescriptor(belongsTo
, col
.RelatedTable
.RelatedDescriptor
);
95 private void CreateHasManyRelations(ActiveRecordDescriptor desc
, TableDefinition tableDef
,
96 IList list
, BuildContext context
)
98 foreach(TableDefinition fkTable
in tableDef
.TablesReferencedByHasRelation
)
100 String propertyName
= _namingService
.CreateRelationName(fkTable
.Name
);
101 ActiveRecordDescriptor targetType
= null;
102 String colName
= null;
103 bool pendentNecessary
= false;
104 ColumnDefinition selectedCol
= null;
106 foreach(ColumnDefinition col
in fkTable
.Columns
)
108 if (col
.RelatedTable
== tableDef
)
112 if (col
.RelatedTable
.RelatedDescriptor
== null && col
.RelatedTable
!= fkTable
)
114 col
.RelatedTable
.RelatedDescriptor
= new ActiveRecordDescriptor(fkTable
);
116 pendentNecessary
= true;
118 else if (col
.RelatedTable
== tableDef
)
123 if (targetType
== null)
125 targetType
= col
.RelatedTable
.RelatedDescriptor
;
134 // Just to protect ourselves from awkward conditions
135 if (colName
== null) continue;
137 ActiveRecordHasManyDescriptor hasMany
=
138 new ActiveRecordHasManyDescriptor(colName
, propertyName
, targetType
);
140 if (pendentNecessary
)
142 context
.AddPendentDescriptor(hasMany
, selectedCol
.RelatedTable
.RelatedDescriptor
);