Skip to content

Commit 2346358

Browse files
Merge pull request diffblue#507 from diffblue/feature/bean-annotation-config
Add bean annotation config
2 parents 280b83d + 71d5d7a commit 2346358

File tree

4 files changed

+56
-45
lines changed

4 files changed

+56
-45
lines changed
Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,43 @@
11
export interface AnnotationConfig {
2-
beans: Beans;
2+
components: Components;
3+
configurations: Configurations;
34
}
45

5-
export interface Beans {
6-
[name: string]: Bean;
6+
export interface Components {
7+
[name: string]: Component;
78
}
89

9-
export interface Bean {
10-
fields: AnnotatedFields;
10+
export interface Component {
11+
isLazyInit: boolean;
12+
fields: AutoWiredFields;
1113
}
1214

13-
export interface AnnotatedFields {
14-
[name: string]: AnnotatedField;
15+
export interface AutoWiredFields {
16+
[name: string]: AutoWiredField;
1517
}
1618

17-
export interface AnnotatedField {
19+
export interface AutoWiredField {
1820
type: string;
1921
}
22+
23+
export interface Configurations {
24+
[name: string]: Configuration;
25+
}
26+
27+
export interface Configuration {
28+
beanDefinitionMethods: BeanDefinitionMethods;
29+
}
30+
31+
export interface BeanDefinitionMethods {
32+
[name: string]: BeanDefinitionMethod;
33+
}
34+
35+
export interface BeanDefinitionMethod {
36+
type: string;
37+
parameterTypes: string[];
38+
scope?: string;
39+
isLazyInit?: boolean;
40+
specifiedName?: string;
41+
initMethod?: string;
42+
destroyMethod?: string;
43+
}

env-model-generator/src/model.ts

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,6 @@ export interface BeanProperty {
2525
value: Value;
2626
}
2727

28-
export enum BeanCreationPolicy {
29-
Singleton,
30-
Lazy,
31-
Keen,
32-
}
33-
3428
interface Factory {
3529
bean: Bean;
3630
method: string;
@@ -40,7 +34,7 @@ export class Bean {
4034
private readonly isAnonymous: boolean;
4135
public readonly name: string;
4236
private readonly impl: string | Factory;
43-
private readonly beanCreationPolicy: BeanCreationPolicy;
37+
private readonly isLazyInit: boolean;
4438
private readonly constructorArgs: Value[];
4539
private readonly properties: NameMap<BeanProperty>;
4640
private readonly initMethod?: string;
@@ -50,7 +44,7 @@ export class Bean {
5044
* @param parent The bean given as a parent for this one
5145
* @param name The name of this bean
5246
* @param impl The name of the class to be instantiated or the details on the factory to use
53-
* @param beanCreationPolicy Whether the bean is created eagerly, statically, etc
47+
* @param isLazyInit Whether the bean is created lazily rather than eagerly
5448
* @param constructorArgs Arguments to pass to the constructor
5549
* @param properties Properties to set after construction
5650
* @param initMethod Method to call after properties are set
@@ -59,7 +53,7 @@ export class Bean {
5953
parent: Bean | undefined,
6054
name: string | undefined,
6155
impl: string | Factory | undefined,
62-
beanCreationPolicy: BeanCreationPolicy | undefined,
56+
isLazyInit: boolean,
6357
constructorArgs: Value[],
6458
properties: BeanProperty[],
6559
initMethod?: string)
@@ -68,15 +62,11 @@ export class Bean {
6862
if (parent) {
6963
if (impl === undefined)
7064
impl = parent.impl;
71-
if (beanCreationPolicy === undefined)
72-
beanCreationPolicy = parent.beanCreationPolicy;
7365
propertiesMap = parent.properties;
7466
if (initMethod === undefined)
7567
initMethod = parent.initMethod;
7668
}
7769
propertiesMap.setRange(properties);
78-
if (beanCreationPolicy === undefined)
79-
throw Error("beanCreationPolicy not specified when parent isn't either");
8070

8171
if (impl === undefined)
8272
throw Error(`Tried to create a Bean ('${name}') without a class name or a factory bean/method`);
@@ -85,7 +75,7 @@ export class Bean {
8575
name = Bean.getNextAnonName(typeof impl === "string" ? impl : impl.bean.identifier + "_" + impl.method);
8676
this.name = name;
8777
this.impl = impl;
88-
this.beanCreationPolicy = beanCreationPolicy;
78+
this.isLazyInit = isLazyInit;
8979
this.constructorArgs = constructorArgs;
9080
this.properties = propertiesMap;
9181
this.initMethod = initMethod;
@@ -117,7 +107,7 @@ export class Bean {
117107
// In the presence of circular dependencies between mutually recursive beans this should really contain the fixed-point set of all possible
118108
// exceptions from all beans on the component
119109
this._exceptions = [];
120-
const variableName = this.beanCreationPolicy === BeanCreationPolicy.Singleton ? `_${this.identifier}` : "value";
110+
const variableName = !this.isLazyInit ? `_${this.identifier}` : "value";
121111
const [ constructorArgs, constructorArgsExceptions ] = collectionToJava(this.constructorArgs);
122112
const [ initialisers, initialisersExceptions ]: [ FnStatement[], string[][] ] =
123113
this.properties.size === 0
@@ -142,7 +132,7 @@ export class Bean {
142132
typeName = "Object";
143133
creatorFn = `${this.impl.bean.getter}().${this.impl.method}`;
144134
}
145-
if (this.beanCreationPolicy !== BeanCreationPolicy.Singleton) {
135+
if (this.isLazyInit) {
146136
this._javaMembers.push(new Method(
147137
`public static ${typeName} ${this.getter}()`,
148138
[

env-model-generator/src/parseJson.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ import { ConfigParseError } from "./configParseError";
44
import * as model from "./model";
55
import { lowerInitialChar } from "./utils";
66

7-
interface BeanWithName {
7+
interface NamedComponent {
88
qualifiedClassName: string;
9-
bean: jsonConfig.Bean;
9+
component: jsonConfig.Component;
1010
}
1111

12-
const beansById = new Map<string, BeanWithName>();
12+
const beansById = new Map<string, NamedComponent>();
1313

1414
export async function collectBeansFromConfigFile(filePath: string): Promise<string[]> {
1515
let json: string;
@@ -19,22 +19,22 @@ export async function collectBeansFromConfigFile(filePath: string): Promise<stri
1919
throw new ConfigParseError(`Can't open input file '${filePath}': ${err.message}`);
2020
}
2121
const annotationConfig: jsonConfig.AnnotationConfig = JSON.parse(json);
22-
for (const qualifiedClassName in annotationConfig.beans) {
23-
if (!annotationConfig.beans.hasOwnProperty(qualifiedClassName))
22+
for (const qualifiedClassName in annotationConfig.components) {
23+
if (!annotationConfig.components.hasOwnProperty(qualifiedClassName))
2424
continue;
2525
// Create bean ID
2626
// TODO: Handle name parameter to @Component constructor
2727
const id = lowerInitialChar(<string>qualifiedClassName.split(".").pop());
2828
// Check for duplicate ids from other beans
2929
if (beansById.has(id))
30-
throw new ConfigParseError(`Found multiple beans with id '${id}'`);
30+
throw new ConfigParseError(`Found multiple components with id '${id}'`);
3131
const aliasedBeanId = model.Bean.getAlias(id);
3232
if (aliasedBeanId !== undefined)
3333
throw new ConfigParseError(`Found a bean with id same as an alias for '${aliasedBeanId}'`);
3434
// Create a bean model for the bean
35-
const bean = { qualifiedClassName: qualifiedClassName, bean: annotationConfig.beans[qualifiedClassName] };
36-
beansById.set(id, bean);
37-
model.Bean.registerIdForClass(bean.qualifiedClassName, id);
35+
const component = { qualifiedClassName: qualifiedClassName, component: annotationConfig.components[qualifiedClassName] };
36+
beansById.set(id, component);
37+
model.Bean.registerIdForClass(component.qualifiedClassName, id);
3838
}
3939
// TODO: Return paths to XML config files specified in code
4040
return [];
@@ -60,21 +60,21 @@ export function parseBean(id: string): model.Bean {
6060
return parseJsonBean(id, bean);
6161
}
6262

63-
function parseJsonBean(id: string | undefined, namedBean: BeanWithName): model.Bean {
64-
const bean = namedBean.bean;
63+
function parseJsonBean(id: string | undefined, namedBean: NamedComponent): model.Bean {
64+
const component = namedBean.component;
6565
const properties: model.BeanProperty[] = [];
66-
for (const fieldName in bean.fields) {
67-
if (!bean.fields.hasOwnProperty(fieldName))
66+
for (const fieldName in component.fields) {
67+
if (!component.fields.hasOwnProperty(fieldName))
6868
continue;
69-
const fieldClass = bean.fields[fieldName].type;
69+
const fieldClass = component.fields[fieldName].type;
7070

7171
const fieldBeanId = model.Bean.tryGetIdByClass(fieldClass);
7272
if (fieldBeanId === undefined)
7373
throw new ConfigParseError(
74-
`Autowired field '${namedBean.qualifiedClassName}.${fieldName}' depends on a class '${fieldClass}' `
74+
`Auto-wired field '${namedBean.qualifiedClassName}.${fieldName}' depends on a class '${fieldClass}' `
7575
+ `that has ${model.Bean.hasMultipleBeansForClass(fieldClass) ? "multiple" : "no"} implementations`);
7676
properties.push({ name: fieldName, value: new model.BeanRefValue(fieldBeanId) });
7777
}
7878
// TODO: Handle constructor arguments
79-
return new model.Bean(undefined, id, namedBean.qualifiedClassName, model.BeanCreationPolicy.Singleton, [], properties);
79+
return new model.Bean(undefined, id, namedBean.qualifiedClassName, false, [], properties);
8080
}

env-model-generator/src/parseSpringXml.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,7 @@ function parseXmlBean(id: string | undefined, bean: spring.BeanType): model.Bean
106106
throw new ConfigParseError(
107107
`Couldn't find bean '${bean.factoryBean}' specified as factoryBean of ${id === undefined ? "anonymous bean" : `'${id}'`}`);
108108
}
109-
const creationPolicy =
110-
bean.scope === "prototype"
111-
? bean.lazyInit === "true" ? model.BeanCreationPolicy.Lazy : model.BeanCreationPolicy.Keen
112-
: model.BeanCreationPolicy.Singleton;
109+
const isLazyInit = bean.scope !== undefined && bean.scope !== "prototype" || bean.lazyInit === "true";
113110
// For each constructor argument parse the index and create a map from index to the whole argument object
114111
const constructorArgMap =
115112
new Map((bean.constructorArg || []).map((arg) => [ parseInt(arg.index, 10), arg ] as [ number, spring.ConstructorArgType ]));
@@ -127,7 +124,7 @@ function parseXmlBean(id: string | undefined, bean: spring.BeanType): model.Bean
127124
impl = { bean: factoryBean, method: bean.factoryMethod };
128125
else
129126
impl = bean.class;
130-
return new model.Bean(parent, id, impl, creationPolicy, constructorArgs, properties, bean.initMethod);
127+
return new model.Bean(parent, id, impl, isLazyInit, constructorArgs, properties, bean.initMethod);
131128
}
132129

133130
function parseProperty(property: any): model.Value {

0 commit comments

Comments
 (0)