Skip to content

Commit f33b5bf

Browse files
committed
Models and Collections
1 parent e6b8f32 commit f33b5bf

File tree

6 files changed

+109
-35
lines changed

6 files changed

+109
-35
lines changed

projects/angular-odata/schematics/apigen/angular/base.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,63 @@ export class Callable {
152152
return this.${baseMethod}(${parametersCall}, this.${methodResourceName}(${key}), '${responseType}', options);
153153
}`;
154154
}
155+
156+
callableMethod() {
157+
const isFunction = this.callable instanceof CsdlFunction;
158+
const { binding, required, optional } = this.parameters();
159+
const parameters = [...required, ...optional];
160+
const returnType = this.returnType();
161+
const callableNamespaceQualifiedName = this.callable.IsBound ? this.callable.fullName() : this.callable.Name;
162+
163+
const methodName = strings.camelize(this.callable.Name);
164+
const responseType =
165+
returnType === undefined
166+
? 'none'
167+
: returnType?.Collection
168+
? 'collection'
169+
: returnType?.Type.startsWith('Edm.')
170+
? 'property'
171+
: 'model';
172+
const retType = returnType === undefined ? 'null' : toTypescriptType(returnType.Type);
173+
174+
const baseMethod = isFunction ? 'callFunction' : 'callAction';
175+
const parametersCall =
176+
parameters.length === 0 ? 'null' : `{${parameters.map((p) => p.Name).join(', ')}}`;
177+
178+
// Method arguments
179+
let args: string[] = [];
180+
args = [
181+
...args,
182+
...(required.length === 0
183+
? []
184+
: required.map((p) => `${p.Name}: ${toTypescriptType(p.Type)}`)),
185+
];
186+
args = [
187+
...args,
188+
...(optional.length === 0
189+
? []
190+
: optional.map((p) => `${p.Name}?: ${toTypescriptType(p.Type)}`)),
191+
];
192+
const optionsType =
193+
returnType !== undefined && returnType.Type.startsWith('Edm.')
194+
? isFunction
195+
? 'ODataOptions & {alias?: boolean}'
196+
: 'ODataOptions'
197+
: isFunction
198+
? `ODataFunctionOptions<${retType}>`
199+
: `ODataActionOptions<${retType}>`;
200+
const fargs = [...args, `options?: ${optionsType}`];
201+
202+
let types = 'null';
203+
if (parameters.length > 0) {
204+
types = `{${args.join(', ')}}`;
205+
}
206+
207+
// Render
208+
return `public ${methodName}(${fargs.join(', ')}) {
209+
return this.${baseMethod}<${types}, ${retType}>('${callableNamespaceQualifiedName}', ${parametersCall}, '${responseType}', options);
210+
}`;
211+
}
155212
}
156213

157214
export abstract class Base {

projects/angular-odata/schematics/apigen/angular/collection.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export class Collection extends Base {
3131
baseType: this.edmType.BaseType ? this.edmType.BaseType + 'Collection' : null,
3232
entity: this.entity,
3333
model: this.model,
34-
actions: [],
34+
callables: this.callables ?? [],
3535
functions: [],
3636
};
3737
}

projects/angular-odata/schematics/apigen/angular/model.ts

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ export class ModelField {
2626
{
2727
type = enumType.importedName!;
2828
type += this.edmType.Collection ? '[]' : '';
29-
} else if (entityType !== undefined) {
29+
}
30+
else if (entityType !== undefined) {
3031
if (this.edmType.Collection) {
3132
const collection = pkg.findCollection(this.edmType.Type);
3233
const model = pkg.findModel(this.edmType.Type);
@@ -38,60 +39,80 @@ export class ModelField {
3839
} else {
3940
type = toTypescriptType(this.edmType.Type);
4041
type += this.edmType.Collection ? '[]' : '';
41-
}
42+
}
4243
return type;
4344
}
4445

4546
resource() {
47+
const pkg = this.model.getPackage();
4648
const resourceName = `$$${this.edmType.Name}`;
4749
if (this.edmType instanceof CsdlNavigationProperty) {
48-
const nav = this.edmType as CsdlNavigationProperty;
50+
const entity = pkg.findEntity(this.edmType.Type);
4951
return `public ${resourceName}() {
50-
return this.navigationProperty<${this.type()}>('${this.edmType.Name}');
51-
}`
52+
return this.navigationProperty<${entity?.importedName}>('${this.edmType.Name}');
53+
}
54+
`
5255
}
5356
else {
5457
return `public ${resourceName}() {
5558
return this.property<${this.type()}>('${this.edmType.Name}');
56-
}`
59+
}
60+
`
5761
}
5862
}
5963

6064
getter() {
65+
const pkg = this.model.getPackage();
6166
const getterName = `$${this.edmType.Name}`;
6267
if (this.edmType instanceof CsdlNavigationProperty) {
63-
const nav = this.edmType as CsdlNavigationProperty;
64-
return "";
68+
const entity = pkg.findEntity(this.edmType.Type);
69+
return `public ${getterName}() {
70+
return this.getAttribute<${entity?.importedName}>('${this.edmType.Name}') as ${entity?.importedName};
71+
}
72+
`
6573
} else {
6674
return `public ${getterName}() {
6775
return this.getAttribute<${this.type()}>('${this.edmType.Name}') as ${this.type()};
68-
}`
76+
}
77+
`
6978
}
7079
}
7180

7281
setter() {
82+
const pkg = this.model.getPackage();
7383
const setterName = `${this.edmType.Name}$$`;
7484
if (this.edmType instanceof CsdlNavigationProperty) {
75-
const nav = this.edmType as CsdlNavigationProperty;
76-
return "";
77-
} else {
85+
const entity = pkg.findEntity(this.edmType.Type);
7886
return `public ${setterName}(model: ${this.type()} | null, options?: ODataOptions) {
79-
return this.setReference<${this.type()}>('${this.edmType.Name}', model, options);
80-
}`
87+
return this.setReference<${entity?.importedName}>('${this.edmType.Name}', model, options);
88+
}
89+
`
90+
} else {
91+
return `
92+
`;
8193
}
8294
}
8395

8496
fetch() {
97+
const pkg = this.model.getPackage();
8598
const fetchName = `${this.edmType.Name}$`;
8699
if (this.edmType instanceof CsdlNavigationProperty) {
87-
const nav = this.edmType as CsdlNavigationProperty;
88-
return "";
100+
const entity = pkg.findEntity(this.edmType.Type);
101+
return `public ${fetchName}(options?: ODataQueryArgumentsOptions<${entity?.importedName}>) {
102+
return this.fetchAttribute<${entity?.importedName}>('${this.edmType.Name}', options) as Observable<${entity?.importedName}>;
103+
}
104+
`
89105
} else {
90106
return `public ${fetchName}(options?: ODataQueryArgumentsOptions<${this.type()}>) {
91107
return this.fetchAttribute<${this.type()}>('${this.edmType.Name}', options) as Observable<${this.type()}>;
92-
}`
108+
}
109+
`
93110
}
94111
}
112+
113+
isGeoSpatial(): boolean {
114+
return this.edmType.Type.startsWith('Edm.Geography') || this.edmType.Type.startsWith('Edm.Geometry');
115+
}
95116
}
96117

97118
export class Model extends Base {
@@ -120,9 +141,8 @@ export class Model extends Base {
120141
...(this.edmType.Property ?? []).map((p) => new ModelField(this, p)),
121142
...(this.edmType.NavigationProperty ?? []).map((p) => new ModelField(this, p)),
122143
],
123-
actions: [], // To be implemented
124-
functions: [], // To be implemented
125-
navigations: [], // To be implemented
144+
callables: this.callables ?? [],
145+
navigations: [],
126146
};
127147
}
128148
public override name() {

projects/angular-odata/schematics/apigen/angular/package.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,11 @@ export class Package {
169169
}
170170

171171
findModel(fullName: string): Model | undefined {
172-
return this.models.find((m) => m.fullName() === fullName);
172+
return this.models.find((m) => m.entityType() === fullName);
173173
}
174174

175175
findCollection(fullName: string): Collection | undefined {
176-
return this.collections.find((c) => c.fullName() === fullName);
176+
return this.collections.find((c) => c.entityType() === fullName);
177177
}
178178

179179
}

projects/angular-odata/schematics/apigen/files/collection/__fileName__.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import {
1313
import { <%= imp.names.join(", ") %> } from '<%= imp.path() %>';<% } %>
1414

1515
export class <%= classify(name) %><E extends <%= entity.name() %>, M extends <%= model.name() %><E>> extends <% if (baseType) { %><%= toTypescriptType(baseType) %><E, M><% } else { %>ODataCollection<E, M><% } %> {
16-
<% for (let action of actions) { %><%= action %>
17-
<% } %>
18-
<% for (let func of functions) { %><%= func %>
19-
<% } %>
16+
<% for (let cal of callables) { %>
17+
// <%= cal.name() %>
18+
<%= cal.callableMethod() %>
19+
<% } %>
2020
}

projects/angular-odata/schematics/apigen/files/model/__fileName__.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,12 @@ import { <%= imp.names.join(", ") %> } from '<%= imp.path() %>';<% } %>
1919
export class <%= classify(name) %><E extends <%= entity.name() %>> extends <% if (baseType) { %><%= toTypescriptType(baseType) %><E><% } else { %>ODataModel<E><% } %> {
2020
<% for (let field of fields) { %>@ModelField()
2121
<%= field.name() %>: <%= field.type() %>;
22-
<%= field.resource() %>
23-
<%= field.getter() %>
24-
<%= field.setter() %>
25-
<%= field.fetch() %>
26-
<% } %>
27-
<% for (let action of actions) { %><%= action %>
28-
<% } %>
29-
<% for (let func of functions) { %><%= func %>
22+
<%= field.resource() %><%= field.getter() %><%= field.setter() %><%= field.fetch() %>
3023
<% } %>
24+
<% for (let cal of callables) { %>
25+
// <%= cal.name() %>
26+
<%= cal.callableMethod() %>
27+
<% } %>
3128
<% for (let nav of navigations) { %><%= nav %>
3229
<% } %>
3330
}

0 commit comments

Comments
 (0)