001/* 002 * ============================================================================ 003 * Copyright © 2002-2021 by Thomas Thrien. 004 * All Rights Reserved. 005 * ============================================================================ 006 * Licensed to the public under the agreements of the GNU Lesser General Public 007 * License, version 3.0 (the "License"). You may obtain a copy of the License at 008 * 009 * http://www.gnu.org/licenses/lgpl.html 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 014 * License for the specific language governing permissions and limitations 015 * under the License. 016 */ 017 018package org.tquadrat.foundation.config.ap.impl; 019 020import static java.util.Arrays.copyOfRange; 021import static org.apiguardian.api.API.Status.INTERNAL; 022import static org.tquadrat.foundation.config.ap.CollectionKind.NO_COLLECTION; 023import static org.tquadrat.foundation.config.ap.PropertySpec.PropertyFlag.ENVIRONMENT_VARIABLE; 024import static org.tquadrat.foundation.config.ap.PropertySpec.PropertyFlag.GETTER_IS_DEFAULT; 025import static org.tquadrat.foundation.config.ap.PropertySpec.PropertyFlag.PROPERTY_IS_SPECIAL; 026import static org.tquadrat.foundation.config.ap.PropertySpec.PropertyFlag.SYSTEM_PREFERENCE; 027import static org.tquadrat.foundation.config.ap.PropertySpec.PropertyFlag.SYSTEM_PROPERTY; 028import static org.tquadrat.foundation.config.ap.impl.codebuilders.CodeGeneratorContext.getAddMethodComposer; 029import static org.tquadrat.foundation.config.ap.impl.codebuilders.CodeGeneratorContext.getConstructorFragment4EnvironmentComposer; 030import static org.tquadrat.foundation.config.ap.impl.codebuilders.CodeGeneratorContext.getConstructorFragment4SystemPreferenceComposer; 031import static org.tquadrat.foundation.config.ap.impl.codebuilders.CodeGeneratorContext.getConstructorFragment4SystemPropComposer; 032import static org.tquadrat.foundation.config.ap.impl.codebuilders.CodeGeneratorContext.getFieldComposer; 033import static org.tquadrat.foundation.config.ap.impl.codebuilders.CodeGeneratorContext.getGetterComposer; 034import static org.tquadrat.foundation.config.ap.impl.codebuilders.CodeGeneratorContext.getSetterComposer; 035import static org.tquadrat.foundation.lang.CommonConstants.NUL; 036import static org.tquadrat.foundation.lang.Objects.isNull; 037import static org.tquadrat.foundation.lang.Objects.mapNonNull; 038import static org.tquadrat.foundation.lang.Objects.nonNull; 039import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument; 040import static org.tquadrat.foundation.lang.Objects.requireNotEmptyArgument; 041import static org.tquadrat.foundation.util.StringUtils.isEmptyOrBlank; 042import static org.tquadrat.foundation.util.StringUtils.isNotEmptyOrBlank; 043 044import javax.lang.model.element.ExecutableElement; 045import javax.lang.model.element.Name; 046import java.util.EnumSet; 047import java.util.List; 048import java.util.Optional; 049import java.util.OptionalInt; 050import java.util.function.BiFunction; 051 052import org.apiguardian.api.API; 053import org.tquadrat.foundation.annotation.ClassVersion; 054import org.tquadrat.foundation.config.INIValue; 055import org.tquadrat.foundation.config.SpecialPropertyType; 056import org.tquadrat.foundation.config.ap.CollectionKind; 057import org.tquadrat.foundation.config.ap.PropertySpec; 058import org.tquadrat.foundation.javacomposer.CodeBlock; 059import org.tquadrat.foundation.javacomposer.FieldSpec; 060import org.tquadrat.foundation.javacomposer.JavaComposer; 061import org.tquadrat.foundation.javacomposer.MethodSpec; 062import org.tquadrat.foundation.javacomposer.TypeName; 063 064/** 065 * The implementation for 066 * {@link PropertySpec}. 067 * 068 * @extauthor Thomas Thrien - thomas.thrien@tquadrat.org 069 * @version $Id: PropertySpecImpl.java 1053 2023-03-11 00:10:49Z tquadrat $ 070 * @since 0.1.0 071 * @UMLGraph.link 072 */ 073@SuppressWarnings( {"ClassWithTooManyFields", "OverlyComplexClass"} ) 074@ClassVersion( sourceVersion = "$Id: PropertySpecImpl.java 1053 2023-03-11 00:10:49Z tquadrat $" ) 075@API( status = INTERNAL, since = "0.1.0" ) 076public final class PropertySpecImpl implements PropertySpec 077{ 078 /*------------*\ 079 ====** Attributes **======================================================= 080 \*------------*/ 081 /** 082 * The name for the 'add' method's argument. 083 */ 084 private Name m_AddMethodArgumentName = null; 085 086 /** 087 * The builder for the 'add' method of this property. 088 */ 089 private MethodSpec.Builder m_AddMethodBuilder = null; 090 091 /** 092 * The method that creates the 'add' method for this property. 093 */ 094 private BiFunction<CodeBuilder,PropertySpecImpl,MethodSpec> m_AddMethodComposer; 095 096 /** 097 * The name for the 'add'' method. 098 */ 099 private Name m_AddMethodName; 100 101 /** 102 * The argument index. 103 * 104 * @see org.tquadrat.foundation.config.Argument#index() 105 */ 106 private int m_CLIArgumentIndex = -1; // -1 means that the value was not set 107 108 /** 109 * The special CLI format. 110 * 111 * @see org.tquadrat.foundation.config.Argument#format() 112 * @see org.tquadrat.foundation.config.Option#format() 113 */ 114 private String m_CLIFormat = null; 115 116 /** 117 * The CLI meta variable. 118 * 119 * @see org.tquadrat.foundation.config.Argument#metaVar() 120 * @see org.tquadrat.foundation.config.Option#metaVar() 121 */ 122 private String m_CLIMetaVar = null; 123 124 /** 125 * The names for a CLI option. 126 * 127 * @see org.tquadrat.foundation.config.Option#name() 128 * @see org.tquadrat.foundation.config.Option#aliases() 129 */ 130 private List<String> m_CLIOptionNames = null; 131 132 /** 133 * The CLI value handler class. 134 * 135 * @see org.tquadrat.foundation.config.Argument#handler() 136 * @see org.tquadrat.foundation.config.Option#handler() 137 */ 138 private TypeName m_CLIValueHandlerClass = null; 139 140 /** 141 * The CLI usage text. 142 * 143 * @see org.tquadrat.foundation.config.Argument#usage() 144 * @see org.tquadrat.foundation.config.Option#usage() 145 */ 146 private String m_CLIUsage = null; 147 148 /** 149 * The CLI usage key. 150 * 151 * @see org.tquadrat.foundation.config.Argument#usageKey() 152 * @see org.tquadrat.foundation.config.Option#usageKey() 153 */ 154 private String m_CLIUsageKey = null; 155 156 /** 157 * The kind of collection for this property. 158 */ 159 private CollectionKind m_CollectionKind = NO_COLLECTION; 160 161 /** 162 * The method that creates the constructor fragment for the initialisation 163 * of this property. 164 */ 165 private BiFunction<CodeBuilder,PropertySpecImpl, CodeBlock> m_ConstructorFragmentComposer; 166 167 /** 168 * The default value for environment variables or system properties. 169 */ 170 private String m_EnvironmentDefaultValue = null; 171 172 /** 173 * The name of the environment variable that is used to initialise this 174 * property. 175 */ 176 private String m_EnvironmentVariableName = null; 177 178 /** 179 * The method that creates the field for this property. 180 */ 181 private BiFunction<CodeBuilder,PropertySpecImpl,FieldSpec> m_FieldComposer; 182 183 /** 184 * The name of the field for the property. 185 */ 186 private String m_FieldName = null; 187 188 /** 189 * The builder for the getter of this property. 190 */ 191 private MethodSpec.Builder m_GetterBuilder = null; 192 193 /** 194 * The method that creates the getter for this property. 195 */ 196 private BiFunction<CodeBuilder,PropertySpecImpl,MethodSpec> m_GetterComposer; 197 198 /** 199 * The name for the getter method. 200 */ 201 private Name m_GetterMethodName = null; 202 203 /** 204 * The return type for the getter method. 205 */ 206 private TypeName m_GetterReturnType; 207 208 /** 209 * The comment for this property when stored in an {@code INI} file. 210 */ 211 private String m_INIComment = null; 212 213 /** 214 * The group for this property when stored in an {@code INI} file. 215 */ 216 private String m_INIGroup = null; 217 218 /** 219 * The key for this property when stored in an {@code INI} file. 220 */ 221 private String m_INIKey = null; 222 223 /** 224 * The flag that indicates whether the property type is an {@code enum} 225 * type. 226 */ 227 private boolean m_IsEnum = false; 228 229 /** 230 * <p>{@summary The {@code Preferences} accessor class.}</p> 231 * <p>This is used when this property is linked to a preference, but also 232 * to initialise it from a SYSTEM preference.</p> 233 * 234 * @see org.tquadrat.foundation.config.Preference#accessor() 235 * @see org.tquadrat.foundation.config.SystemPreference#accessor() 236 */ 237 private TypeName m_PrefsAccessorClass = null; 238 239 /** 240 * <p>{@summary The {@code Preferences} key.}</p> 241 * <p>This is used when this property is linked to a preference, but also 242 * to initialise it from a SYSTEM preference. In first case, the name is 243 * defaulted to the property name, while it is mandatory otherwise.</p> 244 * 245 * @see org.tquadrat.foundation.config.Preference#key() 246 * @see org.tquadrat.foundation.config.SystemPreference#key() 247 */ 248 private String m_PrefsKey = null; 249 250 /** 251 * The property flags. 252 */ 253 private final EnumSet<PropertyFlag> m_PropertyFlags = EnumSet.noneOf( PropertyFlag.class ); 254 255 /** 256 * The name of the property. 257 */ 258 private final String m_PropertyName; 259 260 /** 261 * The type of the property. 262 */ 263 private TypeName m_PropertyType; 264 265 /** 266 * The name for the setter's argument. 267 */ 268 private Name m_SetterArgumentName = null; 269 270 /** 271 * The builder for the setter of this property. 272 */ 273 private MethodSpec.Builder m_SetterBuilder = null; 274 275 /** 276 * The method that creates the setter for this property. 277 */ 278 private BiFunction<CodeBuilder,PropertySpecImpl,MethodSpec> m_SetterComposer; 279 280 /** 281 * The name for the setter method. 282 */ 283 private Name m_SetterMethodName; 284 285 /** 286 * The speciality type for this property; usually, this is {@code null}. 287 */ 288 private SpecialPropertyType m_SpecialPropertyType = null; 289 290 /** 291 * The class that implements the String converter for the type of this 292 * property. 293 */ 294 private TypeName m_StringConverterClass = null; 295 296 /** 297 * The path for the SYSTEM preferences node that holds the initialisation 298 * data for this property. 299 * 300 * @see org.tquadrat.foundation.config.SystemPreference#path() 301 */ 302 private String m_SystemPrefsPath = null; 303 304 /** 305 * The name of the system property that is used to initialise this 306 * property. 307 */ 308 private String m_SystemPropertyName = null; 309 310 /*------------------------*\ 311 ====** Static Initialisations **=========================================== 312 \*------------------------*/ 313 314 /*--------------*\ 315 ====** Constructors **===================================================== 316 \*--------------*/ 317 /** 318 * Creates a new {@code PropertySpecImpl} instance. 319 * 320 * @param propertyName The name of the property. 321 */ 322 public PropertySpecImpl( final String propertyName ) 323 { 324 m_PropertyName = requireNotEmptyArgument( propertyName, "propertyName" ); 325 } // PropertySpecImpl() 326 327 /*---------*\ 328 ====** Methods **========================================================== 329 \*---------*/ 330 /** 331 * {@inheritDoc} 332 */ 333 @Override 334 public final Optional<MethodSpec> createAddMethod( final CodeBuilder codeBuilder ) 335 { 336 final Optional<MethodSpec> retValue = isNull( m_AddMethodComposer ) || hasFlag( GETTER_IS_DEFAULT ) 337 ? Optional.empty() 338 : Optional.of( m_AddMethodComposer.apply( requireNonNullArgument( codeBuilder, "codeBuilder" ), this ) ); 339 340 //---* Done *---------------------------------------------------------- 341 return retValue; 342 } // createAddMethod() 343 344 /** 345 * {@inheritDoc} 346 */ 347 @Override 348 public Optional<CodeBlock> createConstructorFragment( final CodeBuilder codeBuilder ) 349 { 350 final Optional<CodeBlock> retValue = isNull( m_ConstructorFragmentComposer ) || hasFlag( GETTER_IS_DEFAULT ) 351 ? Optional.empty() 352 : Optional.of( m_ConstructorFragmentComposer.apply( requireNonNullArgument( codeBuilder, "codeBuilder" ), this ) ); 353 354 //---* Done *---------------------------------------------------------- 355 return retValue; 356 } // createConstructorFragment() 357 358 /** 359 * {@inheritDoc} 360 */ 361 @Override 362 public final Optional<FieldSpec> createField( final CodeBuilder codeBuilder ) 363 { 364 final Optional<FieldSpec> retValue = isNull( m_FieldComposer ) || hasFlag( GETTER_IS_DEFAULT ) 365 ? Optional.empty() 366 : Optional.of( m_FieldComposer.apply( requireNonNullArgument( codeBuilder, "codeBuilder" ), this ) ); 367 368 //---* Done *---------------------------------------------------------- 369 return retValue; 370 } // createField() 371 372 /** 373 * {@inheritDoc} 374 */ 375 @Override 376 public Optional<MethodSpec> createGetter( final CodeBuilder codeBuilder ) 377 { 378 final Optional<MethodSpec> retValue = isNull( m_GetterComposer ) || hasFlag( GETTER_IS_DEFAULT ) 379 ? Optional.empty() 380 : Optional.of( m_GetterComposer.apply( requireNonNullArgument( codeBuilder, "codeBuilder" ), this ) ); 381 382 //---* Done *---------------------------------------------------------- 383 return retValue; 384 } // createGetter() 385 386 /** 387 * {@inheritDoc} 388 */ 389 @Override 390 public Optional<MethodSpec> createSetter( final CodeBuilder codeBuilder ) 391 { 392 final Optional<MethodSpec> retValue = isNull( m_SetterComposer ) || hasFlag( GETTER_IS_DEFAULT ) 393 ? Optional.empty() 394 : Optional.of( m_SetterComposer.apply( requireNonNullArgument( codeBuilder, "codeBuilder" ), this ) ); 395 396 //---* Done *---------------------------------------------------------- 397 return retValue; 398 } // createSetter() 399 400 /** 401 * {@inheritDoc} 402 */ 403 @Override 404 public final Name getAddMethodArgumentName() { return m_AddMethodArgumentName; } 405 406 /** 407 * <p>{@summary Returns a builder for the 'add' method for this 408 * property.}</p> 409 * <p>This is a convenience method that allows to benefit from 410 * {@link JavaComposer#createMethod(ExecutableElement)}.</p> 411 * 412 * @return An instance of 413 * {@link Optional} 414 * that holds the builder. 415 */ 416 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 417 public final Optional<MethodSpec.Builder> getAddMethodBuilder() { return Optional.ofNullable( m_AddMethodBuilder ); } 418 419 /** 420 * {@inheritDoc} 421 */ 422 @Override 423 public final Optional<Name> getAddMethodName() { return Optional.ofNullable( m_AddMethodName ); } 424 425 /** 426 * {@inheritDoc} 427 */ 428 @Override 429 public final OptionalInt getCLIArgumentIndex() { return m_CLIArgumentIndex < 0 ? OptionalInt.empty() : OptionalInt.of( m_CLIArgumentIndex ); } 430 431 /** 432 * {@inheritDoc} 433 */ 434 @Override 435 public final Optional<String> getCLIFormat() { return Optional.ofNullable( m_CLIFormat ); } 436 437 /** 438 * {@inheritDoc} 439 */ 440 @Override 441 public final Optional<String> getCLIMetaVar() { return Optional.ofNullable( m_CLIMetaVar ); } 442 443 /** 444 * {@inheritDoc} 445 */ 446 @SuppressWarnings( "OptionalContainsCollection" ) 447 @Override 448 public final Optional<List<String>> getCLIOptionNames() { return Optional.ofNullable( m_CLIOptionNames ); } 449 450 /** 451 * {@inheritDoc} 452 */ 453 @Override 454 public final Optional<String> getCLIUsage() { return Optional.ofNullable( m_CLIUsage ); } 455 456 /** 457 * {@inheritDoc} 458 */ 459 @Override 460 public final Optional<String> getCLIUsageKey() { return Optional.ofNullable( m_CLIUsageKey ); } 461 462 /** 463 * {@inheritDoc} 464 */ 465 @Override 466 public final Optional<TypeName> getCLIValueHandlerClass() { return Optional.ofNullable( m_CLIValueHandlerClass ); } 467 468 /** 469 * {@inheritDoc} 470 */ 471 @Override 472 public final CollectionKind getCollectionKind() { return m_CollectionKind; } 473 474 /** 475 * {@inheritDoc} 476 */ 477 @Override 478 public final Optional<String> getEnvironmentDefaultValue() { return Optional.ofNullable( m_EnvironmentDefaultValue ); } 479 480 /** 481 * {@inheritDoc} 482 */ 483 @Override 484 public final Optional<String> getEnvironmentVariableName() { return Optional.ofNullable( m_EnvironmentVariableName ); } 485 486 /** 487 * {@inheritDoc} 488 */ 489 @Override 490 public final String getFieldName() 491 { 492 final var retValue = isEmptyOrBlank( m_FieldName ) ? PropertySpec.super.getFieldName() : m_FieldName; 493 494 //---* Done *---------------------------------------------------------- 495 return retValue; 496 } // getFieldName() 497 498 /** 499 * {@inheritDoc} 500 */ 501 @Override 502 public final Optional<MethodSpec.Builder> getGetterBuilder() { return Optional.ofNullable( m_GetterBuilder ); } 503 504 /** 505 * {@inheritDoc} 506 */ 507 @Override 508 public final Optional<Name> getGetterMethodName() { return Optional.ofNullable( m_GetterMethodName ); } 509 510 /** 511 * {@inheritDoc} 512 */ 513 @Override 514 public final TypeName getGetterReturnType() { return m_GetterReturnType; } 515 516 /** 517 * {@inheritDoc} 518 */ 519 @Override 520 public Optional<String> getINIComment() { return Optional.ofNullable( m_INIComment ); } 521 522 /** 523 * {@inheritDoc} 524 */ 525 @Override 526 public Optional<String> getINIGroup() { return Optional.ofNullable( m_INIGroup ); } 527 528 /** 529 * {@inheritDoc} 530 */ 531 @Override 532 public Optional<String> getINIKey() { return Optional.ofNullable( m_INIKey ); } 533 534 /** 535 * {@inheritDoc} 536 */ 537 @Override 538 public final Optional<TypeName> getPrefsAccessorClass() { return Optional.ofNullable( m_PrefsAccessorClass ); } 539 540 /** 541 * {@inheritDoc} 542 */ 543 @Override 544 public final Optional<String> getPrefsKey() { return Optional.ofNullable( m_PrefsKey ); } 545 546 /** 547 * {@inheritDoc} 548 */ 549 @Override 550 public final String getPropertyName() { return m_PropertyName; } 551 552 /** 553 * {@inheritDoc} 554 */ 555 @Override 556 public final TypeName getPropertyType() { return m_PropertyType; } 557 558 /** 559 * {@inheritDoc} 560 */ 561 @Override 562 public final Name getSetterArgumentName() { return m_SetterArgumentName; } 563 564 /** 565 * {@inheritDoc} 566 */ 567 @Override 568 public final Optional<MethodSpec.Builder> getSetterBuilder() { return Optional.ofNullable( m_SetterBuilder ); } 569 570 /** 571 * {@inheritDoc} 572 */ 573 @Override 574 public final Optional<Name> getSetterMethodName() { return Optional.ofNullable( m_SetterMethodName ); } 575 576 /** 577 * {@inheritDoc} 578 */ 579 @Override 580 public final Optional<SpecialPropertyType> getSpecialPropertyType() { return Optional.ofNullable( m_SpecialPropertyType ); } 581 582 /** 583 * {@inheritDoc} 584 */ 585 @Override 586 public final Optional<TypeName> getStringConverterClass() { return Optional.ofNullable( m_StringConverterClass ); } 587 588 /** 589 * {@inheritDoc} 590 */ 591 @Override 592 public Optional<String> getSystemPrefsPath() 593 { 594 return Optional.ofNullable( m_SystemPrefsPath ); 595 } // getSystemPrefsPath() 596 597 /** 598 * {@inheritDoc} 599 */ 600 @Override 601 public final Optional<String> getSystemPropertyName() { return Optional.ofNullable( m_SystemPropertyName ); } 602 603 /** 604 * {@inheritDoc} 605 */ 606 @Override 607 public final boolean isEnum() { return m_IsEnum; } 608 609 /** 610 * {@inheritDoc} 611 */ 612 @Override 613 public final boolean hasFlag( final PropertyFlag flag ) { return m_PropertyFlags.contains( requireNonNullArgument( flag, "flag" ) ); } 614 615 /** 616 * {@inheritDoc} 617 */ 618 @Override 619 public final PropertySpec merge() 620 { 621 final PropertySpecImpl retValue; 622 if( hasFlag( PROPERTY_IS_SPECIAL ) ) 623 { 624 retValue = new PropertySpecImpl( m_SpecialPropertyType.getPropertyName() ); 625 final var otherSpec = CodeGenerator.getSpecialPropertySpecification( m_SpecialPropertyType ); 626 627 final var flags = EnumSet.copyOf( m_PropertyFlags ); 628 flags.addAll( otherSpec.getAllFlags() ); 629 retValue.setFlag( flags.toArray( PropertyFlag []::new ) ); 630 631 retValue.m_AddMethodArgumentName = m_AddMethodArgumentName; 632 getAddMethodBuilder().ifPresent( retValue::setAddMethodBuilder ); 633 retValue.m_AddMethodComposer = otherSpec.getAddMethodComposer().orElse( m_AddMethodComposer ); 634 getAddMethodName().ifPresent( retValue::setAddMethodName ); 635 getCLIArgumentIndex().ifPresent( retValue::setCLIArgumentIndex ); 636 getCLIFormat().ifPresent( retValue::setCLIFormat ); 637 getCLIMetaVar().ifPresent( retValue::setCLIMetaVar ); 638 getCLIOptionNames().ifPresent( retValue::setCLIOptionNames ); 639 getCLIUsage().ifPresent( retValue::setCLIUsage ); 640 getCLIUsageKey().ifPresent( retValue::setCLIUsageKey ); 641 getCLIValueHandlerClass().ifPresent( retValue::setCLIValueHandlerClass ); 642 retValue.setCollectionKind( otherSpec.getCollectionKind() ); 643 retValue.m_ConstructorFragmentComposer = otherSpec.getConstructorFragmentComposer().orElse( m_ConstructorFragmentComposer ); 644 otherSpec.getEnvironmentDefaultValue().ifPresent( retValue::setEnvironmentDefaultValue ); 645 otherSpec.getEnvironmentVariableName().ifPresentOrElse( retValue::setEnvironmentVariableName, () -> retValue.m_EnvironmentVariableName = null ); 646 retValue.setFieldName( otherSpec.getFieldName() ); // Has a side effect in setting retValue.m_FieldComposer … 647 retValue.m_FieldComposer = otherSpec.getFieldComposer().orElse( m_FieldComposer ); 648 getGetterBuilder().ifPresent( retValue::setGetterBuilder ); 649 getGetterMethodName().ifPresent( retValue::setGetterMethodName ); 650 retValue.m_GetterComposer = otherSpec.getGetterComposer().orElse( m_GetterComposer ); 651 retValue.setGetterReturnType( otherSpec.getGetterReturnType() ); 652 otherSpec.getINIComment().ifPresent( s -> retValue.m_INIComment = s ); 653 otherSpec.getINIGroup().ifPresent( g -> retValue.m_INIGroup = g ); 654 otherSpec.getINIKey().ifPresent( s -> retValue.m_INIKey = s ); 655 retValue.setIsEnum( otherSpec.isEnum() ); 656 otherSpec.getPrefsAccessorClass().ifPresent( retValue::setPrefsAccessorClass ); 657 otherSpec.getPrefsKey().ifPresent( retValue::setPrefsKey ); 658 retValue.setPropertyType( otherSpec.getPropertyType() ); 659 retValue.m_SetterArgumentName = m_SetterArgumentName; 660 otherSpec.getSystemPrefsPath().ifPresent( retValue::setSystemPrefsPath ); 661 getSetterBuilder().ifPresent( retValue::setSetterBuilder ); 662 retValue.m_SetterComposer = otherSpec.getSetterComposer().orElse( m_SetterComposer ); 663 getSetterMethodName().ifPresent( retValue::setSetterMethodName ); 664 retValue.setSpecialPropertyType( m_SpecialPropertyType ); 665 otherSpec.getStringConverterClass().ifPresent( retValue::setStringConverterClass ); 666 otherSpec.getSystemPropertyName().ifPresentOrElse( retValue::setSystemPropertyName, () -> retValue.m_SystemPropertyName = null ); 667 } 668 else 669 { 670 retValue = this; 671 } 672 673 //---* Done *---------------------------------------------------------- 674 return retValue; 675 } // merge() 676 677 /** 678 * Sets the name for the 'add' method's argument. 679 * 680 * @param name The name of the argument. 681 */ 682 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 683 public final void setAddMethodArgumentName( final Name name ) 684 { 685 m_AddMethodArgumentName = requireNonNullArgument( name, "name" ); 686 } // setAddMethodArgumentName() 687 688 /** 689 * Sets the builder for the 'add' method of this property. 690 * 691 * @param builder The builder; can be {@code null}. 692 */ 693 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 694 public final void setAddMethodBuilder( final MethodSpec.Builder builder ) 695 { 696 m_AddMethodBuilder = builder; 697 } // setAddMethodBuilder() 698 699 /** 700 * Sets the name of the 'add'' method for this property. 701 * 702 * @param name The name of the setter method. 703 */ 704 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 705 public final void setAddMethodName( final Name name ) 706 { 707 m_AddMethodName = requireNotEmptyArgument( name, "name" ); 708 m_AddMethodComposer = getAddMethodComposer(); 709 } // setAddMethodName() 710 711 /** 712 * Sets the index for an argument on the command line. 713 * 714 * @param index The index, starting by 0. A negative value indicates, 715 * that the value was not set. 716 * 717 * @see org.tquadrat.foundation.config.Argument#index() 718 */ 719 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 720 public final void setCLIArgumentIndex( final int index ) { m_CLIArgumentIndex = index; } 721 722 /** 723 * Sets the special CLI format. 724 * 725 * @param format The format String; can be {@code null}. 726 * 727 * @see org.tquadrat.foundation.config.Argument#format() 728 * @see org.tquadrat.foundation.config.Option#format() 729 */ 730 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 731 public final void setCLIFormat( final String format ) { m_CLIFormat = format; } 732 733 /** 734 * Sets the CLI meta variable. 735 * 736 * @param metaVar The meta variable; can be {@code null}. 737 * 738 * @see org.tquadrat.foundation.config.Argument#metaVar() 739 * @see org.tquadrat.foundation.config.Option#metaVar() 740 */ 741 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 742 public final void setCLIMetaVar( final String metaVar ) { m_CLIMetaVar = metaVar; } 743 744 /** 745 * <p>{@summary Sets the CLI option names.}</p> 746 * <p>The first entry of the list is the option name, the others are the 747 * aliases.</p> 748 * 749 * @param names The name and the aliases for the CLI option for this 750 * property; can be {@code null}, but may not be empty. 751 * 752 * @see org.tquadrat.foundation.config.Option#name() 753 * @see org.tquadrat.foundation.config.Option#aliases() 754 */ 755 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 756 public final void setCLIOptionNames( final List<String> names ) 757 { 758 m_CLIOptionNames = nonNull( names) ? List.copyOf( requireNotEmptyArgument( names, "names" ) ) : null; 759 } // setCLIOptionNames() 760 761 /** 762 * Sets the CLI usage text. 763 * 764 * @param text The usage text; can be {@code null}. 765 * 766 * @see org.tquadrat.foundation.config.Argument#usage() 767 * @see org.tquadrat.foundation.config.Option#usage() 768 */ 769 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 770 public final void setCLIUsage( final String text ) 771 { 772 m_CLIUsage = text; 773 } // setCLIUsage() 774 775 /** 776 * Sets the CLI usage key. 777 * 778 * @param key The usage key; can be {@code null}. 779 * 780 * @see org.tquadrat.foundation.config.Argument#usageKey() 781 * @see org.tquadrat.foundation.config.Option#usageKey() 782 */ 783 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 784 public final void setCLIUsageKey( final String key ) 785 { 786 m_CLIUsageKey = key; 787 } // setCLIUsageKey() 788 789 /** 790 * Sets the CLI value handler class. 791 * 792 * @param handlerClass The 793 * {@link TypeName} 794 * for the value handler class; can be {@code null}. 795 * 796 * @see org.tquadrat.foundation.config.Argument#handler() 797 * @see org.tquadrat.foundation.config.Option#handler() 798 * @see org.tquadrat.foundation.config.cli.CmdLineValueHandler 799 */ 800 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 801 public final void setCLIValueHandlerClass( final TypeName handlerClass ) 802 { 803 m_CLIValueHandlerClass = handlerClass; 804 } // setCLIValueHandlerClass() 805 806 /** 807 * Sets the kind of collection for this property. 808 * 809 * @param collectionKind The kind of collection. 810 */ 811 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 812 public final void setCollectionKind( final CollectionKind collectionKind ) 813 { 814 m_CollectionKind = requireNonNullArgument( collectionKind, "collectionKind" ); 815 } // setCollectionKind() 816 817 /** 818 * <p>{@summary Sets the default value for an environment variable or a 819 * system property.} This is used to initialise this property when it has 820 * the annotation 821 * {@link org.tquadrat.foundation.config.EnvironmentVariable @EnvironmentVariable} 822 * or 823 * {@link org.tquadrat.foundation.config.SystemProperty @EnvironmentVariable}, 824 * but no value is provided.</p> 825 * <p>A default value is mandatory when the annotated property has a 826 * primitive type.</p> 827 * <p>A String with the only the {@code NUL} character is treated as 828 * {@code null}.</p> 829 * 830 * @param value The default value. 831 */ 832 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 833 public final void setEnvironmentDefaultValue( final String value ) 834 { 835 m_EnvironmentDefaultValue = NUL.equals( value ) ? null : value; 836 } // setEnvironmentDefaultValue() 837 838 /** 839 * Sets the name of the environment variable that provides the (initial) 840 * value for this property. 841 * 842 * @param name The name of the environment variable. 843 */ 844 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 845 public final void setEnvironmentVariableName( final String name ) 846 { 847 m_EnvironmentVariableName = name; 848 if( isNotEmptyOrBlank( name ) ) 849 { 850 m_PropertyFlags.add( ENVIRONMENT_VARIABLE ); 851 m_ConstructorFragmentComposer = getConstructorFragment4EnvironmentComposer(); 852 } 853 else 854 { 855 m_PropertyFlags.remove( ENVIRONMENT_VARIABLE ); 856 m_ConstructorFragmentComposer = null; 857 } 858 } // setEnvironmentVariableName() 859 860 /** 861 * Sets the name of the field for the property. 862 * 863 * @param name The field name. 864 */ 865 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 866 public final void setFieldName( final String name ) 867 { 868 m_FieldName = requireNotEmptyArgument( name, "name" ); 869 m_FieldComposer = getFieldComposer(); 870 } // setFieldName() 871 872 /** 873 * Sets the given flags to the property. 874 * 875 * @param flag The flags to set. 876 */ 877 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 878 public final void setFlag( final PropertyFlag... flag ) 879 { 880 final var length = requireNonNullArgument( flag, "flag" ).length; 881 switch( length ) 882 { 883 case 0: break /* Do nothing */; 884 case 1: m_PropertyFlags.add( flag [0] ); break; 885 case 2: m_PropertyFlags.addAll( EnumSet.of( flag [0], flag [1] ) ); break; 886 default: m_PropertyFlags.addAll( EnumSet.of( flag [0], copyOfRange( flag, 1, length ) ) ); break; 887 } 888 } // setFlag() 889 890 /** 891 * Sets the builder for the getter of this property. 892 * 893 * @param builder The builder; can be {@code null}. 894 */ 895 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 896 public final void setGetterBuilder( final MethodSpec.Builder builder ) 897 { 898 m_GetterBuilder = builder; 899 } // setGetterBuilder() 900 901 /** 902 * Sets the method name for the getter. 903 * 904 * @param name The method name. 905 */ 906 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 907 public final void setGetterMethodName( final Name name ) 908 { 909 m_GetterMethodName = requireNotEmptyArgument( name, "name" ); 910 m_GetterComposer = getGetterComposer(); 911 } // setGetterMethodName() 912 913 /** 914 * Sets the return type for the getter. 915 * 916 * @param type The getter's return type. 917 */ 918 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 919 public final void setGetterReturnType( final TypeName type ) 920 { 921 m_GetterReturnType = requireNonNullArgument( type, "type" ); 922 } // setGetterReturnType() 923 924 /** 925 * Sets the {@code INI} file configuration for this property. 926 * 927 * @param group The group. 928 * @param key The key. 929 * @param comment The comment; can be {@code null}. 930 */ 931 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 932 public final void setINIConfiguration( final String group, final String key, final String comment ) 933 { 934 m_INIComment = comment; 935 m_INIGroup = requireNotEmptyArgument( group, "group" ); 936 m_INIKey = requireNotEmptyArgument( key, "key" ); 937 } // setINIConfiguration() 938 939 /** 940 * Sets the {@code INI} file configuration for this property. 941 * 942 * @param configuration The configuration annotation. 943 */ 944 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 945 public void setINIConfiguration( final INIValue configuration ) 946 { 947 final var group = requireNonNullArgument( configuration, "configuration" ).group(); 948 final var key = mapNonNull( configuration.key(), s -> isEmptyOrBlank( s ) ? getPropertyName() : s ); 949 final var comment = configuration.comment(); 950 setINIConfiguration( group, key, comment ); 951 } // setINIConfiguration() 952 953 /** 954 * Sets the flag that indicates whether the property is an 955 * {@link Enum enum} 956 * type. 957 * 958 * @param flag {@code true} if the property type is an {@code enum} 959 * type, {@code false} otherwise. 960 */ 961 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 962 public final void setIsEnum( final boolean flag ) { m_IsEnum = flag; } 963 964 /** 965 * Sets the preferences accessor class for this property. 966 * 967 * @param accessorClass The accessor class; can be {@code null}. 968 */ 969 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 970 public final void setPrefsAccessorClass( final TypeName accessorClass ) 971 { 972 m_PrefsAccessorClass = accessorClass; 973 } // setPrefsAccessorClass() 974 975 /** 976 * Sets the preferences key for this property. 977 * 978 * @param preferenceKey The key. 979 */ 980 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 981 public final void setPrefsKey( final String preferenceKey ) 982 { 983 m_PrefsKey = preferenceKey; 984 } // setPrefsKey 985 986 /** 987 * Sets the property type. 988 * 989 * @param type The type of the property. 990 */ 991 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 992 public final void setPropertyType( final TypeName type ) 993 { 994 m_PropertyType = requireNonNullArgument( type, "type" ); 995 } // setPropertyType() 996 997 /** 998 * Sets the name for the setter's argument. 999 * 1000 * @param name The name of the argument. 1001 */ 1002 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 1003 public final void setSetterArgumentName( final Name name ) 1004 { 1005 m_SetterArgumentName = requireNonNullArgument( name, "name" ); 1006 } // setSetterArgumentName() 1007 1008 /** 1009 * Sets the builder for the setter of this property. 1010 * 1011 * @param builder The builder; can be {@code null}. 1012 */ 1013 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 1014 public final void setSetterBuilder( final MethodSpec.Builder builder ) 1015 { 1016 m_SetterBuilder = builder; 1017 } // setGetterBuilder() 1018 1019 /** 1020 * Sets the name of the setter method for this property. 1021 * 1022 * @param name The name of the setter method. 1023 */ 1024 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 1025 public void setSetterMethodName( final Name name ) 1026 { 1027 m_SetterMethodName = requireNotEmptyArgument( name, "name" ); 1028 m_SetterComposer = getSetterComposer(); 1029 } // setSetterMethodName() 1030 1031 /** 1032 * Sets the speciality type for this property. 1033 * 1034 * @param type The speciality type. 1035 */ 1036 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 1037 public final void setSpecialPropertyType( final SpecialPropertyType type ) 1038 { 1039 m_SpecialPropertyType = type; 1040 if( nonNull( m_SpecialPropertyType ) ) 1041 { 1042 m_PropertyFlags.add( PROPERTY_IS_SPECIAL ); 1043 } 1044 else 1045 { 1046 m_PropertyFlags.remove( PROPERTY_IS_SPECIAL ); 1047 } 1048 } // setSpecialPropertyType() 1049 1050 /** 1051 * Sets the name for the class that implements 1052 * {@link org.tquadrat.foundation.lang.StringConverter} 1053 * for the type of this property. 1054 * 1055 * @param typeName The String converter class; can be {@code null}. 1056 */ 1057 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 1058 public final void setStringConverterClass( final TypeName typeName ) 1059 { 1060 m_StringConverterClass = typeName; 1061 } // setStringConverterClass() 1062 1063 /** 1064 * Sets the path for the SYSTEM {@code Preferences} node that holds the 1065 * initialisation data for this property. 1066 * 1067 * @param path The path. 1068 */ 1069 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 1070 public final void setSystemPrefsPath( final String path ) 1071 { 1072 m_SystemPrefsPath = path; 1073 if( isNotEmptyOrBlank( path ) ) 1074 { 1075 m_PropertyFlags.add( SYSTEM_PREFERENCE ); 1076 m_ConstructorFragmentComposer = getConstructorFragment4SystemPreferenceComposer(); 1077 } 1078 else 1079 { 1080 m_PropertyFlags.remove( SYSTEM_PREFERENCE ); 1081 m_ConstructorFragmentComposer = null; 1082 } 1083 } // setSystemPrefsPath() 1084 1085 /** 1086 * Sets the name of the system property that provides the (initial) value 1087 * for this property. 1088 * 1089 * @param name The name of the system property. 1090 */ 1091 @SuppressWarnings( "PublicMethodNotExposedInInterface" ) 1092 public final void setSystemPropertyName( final String name ) 1093 { 1094 m_SystemPropertyName = name; 1095 if( isNotEmptyOrBlank( name ) ) 1096 { 1097 m_PropertyFlags.add( SYSTEM_PROPERTY ); 1098 m_ConstructorFragmentComposer = getConstructorFragment4SystemPropComposer(); 1099 } 1100 else 1101 { 1102 m_PropertyFlags.remove( SYSTEM_PROPERTY ); 1103 m_ConstructorFragmentComposer = null; 1104 } 1105 } // setSystemPropertyName() 1106} 1107// class PropertySpecImpl 1108 1109/* 1110 * End of File 1111 */