1616
1717package org .bson .codecs .pojo ;
1818
19+ import org .bson .codecs .configuration .CodecConfigurationException ;
20+
1921import java .lang .annotation .Annotation ;
2022import java .util .ArrayList ;
2123import java .util .Collections ;
4143 * @see ClassModel
4244 */
4345public class ClassModelBuilder <T > {
44- private static final String ID_FIELD_NAME = "_id" ;
45- private final List <FieldModelBuilder <?>> fields = new ArrayList <FieldModelBuilder <?>>();
46+ private static final String ID_PROPERTY_NAME = "_id" ;
47+ private final List <PropertyModelBuilder <?>> propertyModelBuilders = new ArrayList <PropertyModelBuilder <?>>();
4648 private InstanceCreatorFactory <T > instanceCreatorFactory ;
4749 private Class <T > type ;
48- private Map <String , TypeParameterMap > fieldNameToTypeParameterMap = emptyMap ();
50+ private Map <String , TypeParameterMap > propertyNameToTypeParameterMap = emptyMap ();
4951 private List <Convention > conventions = DEFAULT_CONVENTIONS ;
5052 private List <Annotation > annotations = emptyList ();
5153 private boolean discriminatorEnabled ;
5254 private String discriminator ;
5355 private String discriminatorKey ;
54- private String idField ;
56+ private String idPropertyName ;
5557
5658 ClassModelBuilder (final Class <T > type ) {
5759 configureClassModelBuilder (this , notNull ("type" , type ));
@@ -184,59 +186,56 @@ public Boolean useDiscriminator() {
184186 }
185187
186188 /**
187- * Designates a field as the {@code _id} field for this type. If another field is currently marked as the {@code _id} field,
188- * that setting is cleared in favor of the named field.
189+ * Designates a property as the {@code _id} property for this type. If another property is currently marked as the {@code _id}
190+ * property, that setting is cleared in favor of the named property.
191+ *
192+ * @param idPropertyName the property name to use for the {@code _id} property
189193 *
190- * @param idField the FieldModel field name to use for the {@code _id} field
191194 * @return this
192195 */
193- public ClassModelBuilder <T > idField (final String idField ) {
194- this .idField = notNull ("idField " , idField );
196+ public ClassModelBuilder <T > idPropertyName (final String idPropertyName ) {
197+ this .idPropertyName = notNull ("idPropertyName " , idPropertyName );
195198 return this ;
196199 }
197200
198201 /**
199- * @return the designated {@code _id} field for this type or null if not set
202+ * @return the designated {@code _id} property name for this type or null if not set
200203 */
201- public String getIdField () {
202- return idField ;
204+ public String getIdPropertyName () {
205+ return idPropertyName ;
203206 }
204207
205208 /**
206- * Remove a field from the builder
209+ * Remove a property from the builder
207210 *
208- * @param name the actual field name in the POJO and not the {@code documentFieldName }.
209- * @return returns true if the field matched and was removed
211+ * @param propertyName the actual property name in the POJO and not the {@code documentPropertyName }.
212+ * @return returns true if the property matched and was removed
210213 */
211- public boolean removeField (final String name ) {
212- return fields .remove (getField (notNull ("name " , name )));
214+ public boolean removeProperty (final String propertyName ) {
215+ return propertyModelBuilders .remove (getProperty (notNull ("propertyName " , propertyName )));
213216 }
214217
215218 /**
216- * Gets a field by the given name.
217- *
218- * <p>
219- * Note: Searches against the actual field name in the POJO and not the {@code documentFieldName}.
220- * </p>
219+ * Gets a property by the property name.
221220 *
222- * @param name the name of the field to find.
223- * @return the field or null if the field is not found
221+ * @param propertyName the name of the property to find.
222+ * @return the property or null if the property is not found
224223 */
225- public FieldModelBuilder <?> getField (final String name ) {
226- notNull ("name " , name );
227- for (FieldModelBuilder <?> fieldModelBuilder : fields ) {
228- if (fieldModelBuilder . getFieldName ().equals (name )) {
229- return fieldModelBuilder ;
224+ public PropertyModelBuilder <?> getProperty (final String propertyName ) {
225+ notNull ("propertyName " , propertyName );
226+ for (PropertyModelBuilder <?> propertyModelBuilder : propertyModelBuilders ) {
227+ if (propertyModelBuilder . getName ().equals (propertyName )) {
228+ return propertyModelBuilder ;
230229 }
231230 }
232231 return null ;
233232 }
234233
235234 /**
236- * @return the fields on the modeled type
235+ * @return the properties on the modeled type
237236 */
238- public List <FieldModelBuilder <?>> getFields () {
239- return Collections .unmodifiableList (fields );
237+ public List <PropertyModelBuilder <?>> getPropertyModelBuilders () {
238+ return Collections .unmodifiableList (propertyModelBuilders );
240239 }
241240
242241 /**
@@ -245,8 +244,8 @@ public List<FieldModelBuilder<?>> getFields() {
245244 * @return the new instance
246245 */
247246 public ClassModel <T > build () {
248- List <FieldModel <?>> fieldModels = new ArrayList <FieldModel <?>>();
249- FieldModel <?> idFieldModel = null ;
247+ List <PropertyModel <?>> propertyModels = new ArrayList <PropertyModel <?>>();
248+ PropertyModel <?> idPropertyModel = null ;
250249
251250 stateNotNull ("type" , type );
252251 for (Convention convention : conventions ) {
@@ -259,72 +258,71 @@ public ClassModel<T> build() {
259258 stateNotNull ("discriminator" , discriminator );
260259 }
261260
262- for (FieldModelBuilder <?> fieldModelBuilder : fields ) {
263- boolean isIdField = fieldModelBuilder . getFieldName ().equals (idField );
264- if (isIdField ) {
265- fieldModelBuilder . documentFieldName ( ID_FIELD_NAME );
261+ for (PropertyModelBuilder <?> propertyModelBuilder : propertyModelBuilders ) {
262+ boolean isIdProperty = propertyModelBuilder . getName ().equals (idPropertyName );
263+ if (isIdProperty ) {
264+ propertyModelBuilder . readName ( ID_PROPERTY_NAME ). writeName ( ID_PROPERTY_NAME );
266265 }
267266
268- FieldModel <?> model = fieldModelBuilder .build ();
269- fieldModels .add (model );
270- if (isIdField ) {
271- idFieldModel = model ;
267+ PropertyModel <?> model = propertyModelBuilder .build ();
268+ propertyModels .add (model );
269+ if (isIdProperty ) {
270+ idPropertyModel = model ;
272271 }
273272 }
274- validateFieldModels ( fieldModels );
273+ validatePropertyModels ( type . getSimpleName (), propertyModels );
275274
276275
277- return new ClassModel <T >(type , fieldNameToTypeParameterMap , instanceCreatorFactory , discriminatorEnabled , discriminatorKey ,
278- discriminator , idFieldModel , unmodifiableList (fieldModels ));
276+ return new ClassModel <T >(type , propertyNameToTypeParameterMap , instanceCreatorFactory , discriminatorEnabled , discriminatorKey ,
277+ discriminator , idPropertyModel , unmodifiableList (propertyModels ));
279278 }
280279
281280 @ Override
282281 public String toString () {
283282 return format ("ClassModelBuilder{type=%s}" , type );
284283 }
285284
286- Map <String , TypeParameterMap > getFieldNameToTypeParameterMap () {
287- return fieldNameToTypeParameterMap ;
285+ Map <String , TypeParameterMap > getPropertyNameToTypeParameterMap () {
286+ return propertyNameToTypeParameterMap ;
288287 }
289288
290- ClassModelBuilder <T > fieldNameToTypeParameterMap (final Map <String , TypeParameterMap > fieldNameToTypeParameterMap ) {
291- this .fieldNameToTypeParameterMap = unmodifiableMap (new HashMap <String , TypeParameterMap >(fieldNameToTypeParameterMap ));
289+ ClassModelBuilder <T > propertyNameToTypeParameterMap (final Map <String , TypeParameterMap > propertyNameToTypeParameterMap ) {
290+ this .propertyNameToTypeParameterMap = unmodifiableMap (new HashMap <String , TypeParameterMap >(propertyNameToTypeParameterMap ));
292291 return this ;
293292 }
294293
295- ClassModelBuilder <T > addField (final FieldModelBuilder <?> fieldModelBuilder ) {
296- fields .add (notNull ("fieldModelBuilder " , fieldModelBuilder ));
294+ ClassModelBuilder <T > addProperty (final PropertyModelBuilder <?> propertyModelBuilder ) {
295+ propertyModelBuilders .add (notNull ("propertyModelBuilder " , propertyModelBuilder ));
297296 return this ;
298297 }
299298
300- private void validateFieldModels (final List <FieldModel <?>> fieldModels ) {
301- Map <String , Integer > fieldNameMap = new HashMap <String , Integer >();
302- Map <String , Integer > fieldDocumentNameMap = new HashMap <String , Integer >();
303- String duplicateFieldName = null ;
304- String duplicateDocumentFieldName = null ;
305-
306- for (FieldModel <?> fieldModel : fieldModels ) {
307- String fieldName = fieldModel .getFieldName ();
308- if (fieldNameMap .containsKey (fieldName )) {
309- duplicateFieldName = fieldName ;
310- break ;
311- }
312- fieldNameMap .put (fieldName , 1 );
299+ private void validatePropertyModels (final String declaringClass , final List <PropertyModel <?>> propertyModels ) {
300+ Map <String , Integer > propertyNameMap = new HashMap <String , Integer >();
301+ Map <String , Integer > propertyReadNameMap = new HashMap <String , Integer >();
302+ Map <String , Integer > propertyWriteNameMap = new HashMap <String , Integer >();
313303
314- String documentFieldName = fieldModel .getDocumentFieldName ();
315- if (fieldDocumentNameMap .containsKey (documentFieldName )) {
316- duplicateDocumentFieldName = documentFieldName ;
317- break ;
304+ for (PropertyModel <?> propertyModel : propertyModels ) {
305+ checkForDuplicates ("property" , propertyModel .getName (), propertyNameMap , declaringClass );
306+ if (propertyModel .isReadable ()) {
307+ checkForDuplicates ("read property" , propertyModel .getReadName (), propertyReadNameMap , declaringClass );
308+ }
309+ if (propertyModel .isWritable ()) {
310+ checkForDuplicates ("write property" , propertyModel .getWriteName (), propertyWriteNameMap , declaringClass );
318311 }
319- fieldDocumentNameMap .put (documentFieldName , 1 );
320312 }
321- if (idField != null && !fieldNameMap .containsKey (idField )) {
322- throw new IllegalStateException (format ("Invalid id field, field named field '%s' can not be found." , idField ));
323- } else if (duplicateFieldName != null ) {
324- throw new IllegalStateException (format ("Duplicate field named '%s' found." , duplicateFieldName ));
325- } else if (duplicateDocumentFieldName != null ) {
326- throw new IllegalStateException (format ("Duplicate document field named '%s' found." , duplicateDocumentFieldName ));
313+
314+ if (idPropertyName != null && !propertyNameMap .containsKey (idPropertyName )) {
315+ throw new CodecConfigurationException (format ("Invalid id property, property named '%s' can not be found." , idPropertyName ));
316+ }
317+ }
318+
319+ private void checkForDuplicates (final String propertyType , final String propertyName , final Map <String , Integer > propertyNameMap ,
320+ final String declaringClass ) {
321+ if (propertyNameMap .containsKey (propertyName )) {
322+ throw new CodecConfigurationException (format ("Duplicate %s named '%s' found in %s." , propertyType , propertyName ,
323+ declaringClass ));
327324 }
325+ propertyNameMap .put (propertyName , 1 );
328326 }
329327
330328}
0 commit comments