001/* 002 * Copyright 2009-2020 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2009-2020 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2009-2020 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.sdk.persist; 037 038 039 040import java.io.File; 041import java.io.FileWriter; 042import java.io.OutputStream; 043import java.io.PrintWriter; 044import java.io.Serializable; 045import java.util.Arrays; 046import java.util.Collection; 047import java.util.Date; 048import java.util.Iterator; 049import java.util.LinkedHashMap; 050import java.util.TreeMap; 051import java.util.TreeSet; 052 053import com.unboundid.ldap.sdk.DN; 054import com.unboundid.ldap.sdk.Entry; 055import com.unboundid.ldap.sdk.Filter; 056import com.unboundid.ldap.sdk.LDAPConnection; 057import com.unboundid.ldap.sdk.LDAPException; 058import com.unboundid.ldap.sdk.LDAPInterface; 059import com.unboundid.ldap.sdk.ReadOnlyEntry; 060import com.unboundid.ldap.sdk.ResultCode; 061import com.unboundid.ldap.sdk.Version; 062import com.unboundid.ldap.sdk.schema.AttributeTypeDefinition; 063import com.unboundid.ldap.sdk.schema.ObjectClassDefinition; 064import com.unboundid.ldap.sdk.schema.ObjectClassType; 065import com.unboundid.ldap.sdk.schema.Schema; 066import com.unboundid.util.Debug; 067import com.unboundid.util.LDAPCommandLineTool; 068import com.unboundid.util.Mutable; 069import com.unboundid.util.StaticUtils; 070import com.unboundid.util.ThreadSafety; 071import com.unboundid.util.ThreadSafetyLevel; 072import com.unboundid.util.args.ArgumentException; 073import com.unboundid.util.args.ArgumentParser; 074import com.unboundid.util.args.BooleanArgument; 075import com.unboundid.util.args.DNArgument; 076import com.unboundid.util.args.FileArgument; 077import com.unboundid.util.args.StringArgument; 078 079import static com.unboundid.ldap.sdk.persist.PersistMessages.*; 080 081 082 083/** 084 * This class provides a tool which can be used to generate source code for a 085 * Java class file based on information read from the schema of an LDAP 086 * directory server. 087 */ 088@Mutable() 089@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 090public final class GenerateSourceFromSchema 091 extends LDAPCommandLineTool 092 implements Serializable 093{ 094 /** 095 * The serial version UID for this serializable class. 096 */ 097 private static final long serialVersionUID = 3488976364950590266L; 098 099 100 101 /** 102 * A pre-allocated empty tree set. 103 */ 104 private static final TreeSet<String> EMPTY_TREE_SET = new TreeSet<>(); 105 106 107 108 // Arguments used by this tool. 109 private BooleanArgument terseArg; 110 private DNArgument defaultParentDNArg; 111 private FileArgument outputDirectoryArg; 112 private StringArgument auxiliaryClassArg; 113 private StringArgument classNameArg; 114 private StringArgument lazyAttributeArg; 115 private StringArgument operationalAttributeArg; 116 private StringArgument packageNameArg; 117 private StringArgument rdnAttributeArg; 118 private StringArgument structuralClassArg; 119 120 // Indicates whether any multivalued attributes have been identified, and 121 // therefore we need to include java.util.Arrays in the import list. 122 private boolean needArrays; 123 124 // Indicates whether any date attributes have been identified, and therefore 125 // we need to include java.util.Date in the import list. 126 private boolean needDate; 127 128 // Indicates whether any DN-syntax attributes have been identified, and 129 // therefore we need to include com.unboundid.ldap.sdk.DN in the import list. 130 private boolean needDN; 131 132 // Indicates whether 133 // Indicates whether any DN-syntax attributes have been identified, and 134 // therefore we need to include 135 // com.unboundid.ldap.sdk.persist.PersistedObjects in the import list. 136 private boolean needPersistedObjects; 137 138 139 140 /** 141 * Parse the provided command line arguments and perform the appropriate 142 * processing. 143 * 144 * @param args The command line arguments provided to this program. 145 */ 146 public static void main(final String[] args) 147 { 148 final ResultCode resultCode = main(args, System.out, System.err); 149 if (resultCode != ResultCode.SUCCESS) 150 { 151 System.exit(resultCode.intValue()); 152 } 153 } 154 155 156 157 /** 158 * Parse the provided command line arguments and perform the appropriate 159 * processing. 160 * 161 * @param args The command line arguments provided to this program. 162 * @param outStream The output stream to which standard out should be 163 * written. It may be {@code null} if output should be 164 * suppressed. 165 * @param errStream The output stream to which standard error should be 166 * written. It may be {@code null} if error messages 167 * should be suppressed. 168 * 169 * @return A result code indicating whether the processing was successful. 170 */ 171 public static ResultCode main(final String[] args, 172 final OutputStream outStream, 173 final OutputStream errStream) 174 { 175 final GenerateSourceFromSchema tool = 176 new GenerateSourceFromSchema(outStream, errStream); 177 return tool.runTool(args); 178 } 179 180 181 182 /** 183 * Creates a new instance of this tool. 184 * 185 * @param outStream The output stream to which standard out should be 186 * written. It may be {@code null} if output should be 187 * suppressed. 188 * @param errStream The output stream to which standard error should be 189 * written. It may be {@code null} if error messages 190 * should be suppressed. 191 */ 192 public GenerateSourceFromSchema(final OutputStream outStream, 193 final OutputStream errStream) 194 { 195 super(outStream, errStream); 196 197 needArrays = false; 198 needDate = false; 199 needDN = false; 200 needPersistedObjects = false; 201 } 202 203 204 205 /** 206 * {@inheritDoc} 207 */ 208 @Override() 209 public String getToolName() 210 { 211 return "generate-source-from-schema"; 212 } 213 214 215 216 /** 217 * {@inheritDoc} 218 */ 219 @Override() 220 public String getToolDescription() 221 { 222 return INFO_GEN_SOURCE_TOOL_DESCRIPTION.get(); 223 } 224 225 226 227 /** 228 * Retrieves the version string for this tool. 229 * 230 * @return The version string for this tool. 231 */ 232 @Override() 233 public String getToolVersion() 234 { 235 return Version.NUMERIC_VERSION_STRING; 236 } 237 238 239 240 /** 241 * Indicates whether this tool should provide support for an interactive mode, 242 * in which the tool offers a mode in which the arguments can be provided in 243 * a text-driven menu rather than requiring them to be given on the command 244 * line. If interactive mode is supported, it may be invoked using the 245 * "--interactive" argument. Alternately, if interactive mode is supported 246 * and {@link #defaultsToInteractiveMode()} returns {@code true}, then 247 * interactive mode may be invoked by simply launching the tool without any 248 * arguments. 249 * 250 * @return {@code true} if this tool supports interactive mode, or 251 * {@code false} if not. 252 */ 253 @Override() 254 public boolean supportsInteractiveMode() 255 { 256 return true; 257 } 258 259 260 261 /** 262 * Indicates whether this tool defaults to launching in interactive mode if 263 * the tool is invoked without any command-line arguments. This will only be 264 * used if {@link #supportsInteractiveMode()} returns {@code true}. 265 * 266 * @return {@code true} if this tool defaults to using interactive mode if 267 * launched without any command-line arguments, or {@code false} if 268 * not. 269 */ 270 @Override() 271 public boolean defaultsToInteractiveMode() 272 { 273 return true; 274 } 275 276 277 278 /** 279 * Indicates whether this tool should provide arguments for redirecting output 280 * to a file. If this method returns {@code true}, then the tool will offer 281 * an "--outputFile" argument that will specify the path to a file to which 282 * all standard output and standard error content will be written, and it will 283 * also offer a "--teeToStandardOut" argument that can only be used if the 284 * "--outputFile" argument is present and will cause all output to be written 285 * to both the specified output file and to standard output. 286 * 287 * @return {@code true} if this tool should provide arguments for redirecting 288 * output to a file, or {@code false} if not. 289 */ 290 @Override() 291 protected boolean supportsOutputFile() 292 { 293 return true; 294 } 295 296 297 298 /** 299 * Indicates whether this tool should default to interactively prompting for 300 * the bind password if a password is required but no argument was provided 301 * to indicate how to get the password. 302 * 303 * @return {@code true} if this tool should default to interactively 304 * prompting for the bind password, or {@code false} if not. 305 */ 306 @Override() 307 protected boolean defaultToPromptForBindPassword() 308 { 309 return true; 310 } 311 312 313 314 /** 315 * Indicates whether this tool supports the use of a properties file for 316 * specifying default values for arguments that aren't specified on the 317 * command line. 318 * 319 * @return {@code true} if this tool supports the use of a properties file 320 * for specifying default values for arguments that aren't specified 321 * on the command line, or {@code false} if not. 322 */ 323 @Override() 324 public boolean supportsPropertiesFile() 325 { 326 return true; 327 } 328 329 330 331 /** 332 * Indicates whether the LDAP-specific arguments should include alternate 333 * versions of all long identifiers that consist of multiple words so that 334 * they are available in both camelCase and dash-separated versions. 335 * 336 * @return {@code true} if this tool should provide multiple versions of 337 * long identifiers for LDAP-specific arguments, or {@code false} if 338 * not. 339 */ 340 @Override() 341 protected boolean includeAlternateLongIdentifiers() 342 { 343 return true; 344 } 345 346 347 348 /** 349 * Indicates whether this tool should provide a command-line argument that 350 * allows for low-level SSL debugging. If this returns {@code true}, then an 351 * "--enableSSLDebugging}" argument will be added that sets the 352 * "javax.net.debug" system property to "all" before attempting any 353 * communication. 354 * 355 * @return {@code true} if this tool should offer an "--enableSSLDebugging" 356 * argument, or {@code false} if not. 357 */ 358 @Override() 359 protected boolean supportsSSLDebugging() 360 { 361 return true; 362 } 363 364 365 366 /** 367 * {@inheritDoc} 368 */ 369 @Override() 370 public void addNonLDAPArguments(final ArgumentParser parser) 371 throws ArgumentException 372 { 373 outputDirectoryArg = new FileArgument('d', "outputDirectory", false, 1, 374 INFO_GEN_SOURCE_VALUE_PLACEHOLDER_PATH.get(), 375 INFO_GEN_SOURCE_ARG_DESCRIPTION_OUTPUT_DIRECTORY.get(), true, true, 376 false, true); 377 outputDirectoryArg.addLongIdentifier("output-directory", true); 378 parser.addArgument(outputDirectoryArg); 379 380 structuralClassArg = new StringArgument('s', "structuralClass", true, 1, 381 INFO_GEN_SOURCE_VALUE_PLACEHOLDER_NAME.get(), 382 INFO_GEN_SOURCE_ARG_DESCRIPTION_STRUCTURAL_CLASS.get()); 383 structuralClassArg.addLongIdentifier("structural-class", true); 384 parser.addArgument(structuralClassArg); 385 386 auxiliaryClassArg = new StringArgument('a', "auxiliaryClass", false, 0, 387 INFO_GEN_SOURCE_VALUE_PLACEHOLDER_NAME.get(), 388 INFO_GEN_SOURCE_ARG_DESCRIPTION_AUXILIARY_CLASS.get()); 389 auxiliaryClassArg.addLongIdentifier("auxiliary-class", true); 390 parser.addArgument(auxiliaryClassArg); 391 392 rdnAttributeArg = new StringArgument('r', "rdnAttribute", true, 0, 393 INFO_GEN_SOURCE_VALUE_PLACEHOLDER_NAME.get(), 394 INFO_GEN_SOURCE_ARG_DESCRIPTION_RDN_ATTRIBUTE.get()); 395 rdnAttributeArg.addLongIdentifier("rdn-attribute", true); 396 parser.addArgument(rdnAttributeArg); 397 398 lazyAttributeArg = new StringArgument('l', "lazyAttribute", false, 0, 399 INFO_GEN_SOURCE_VALUE_PLACEHOLDER_NAME.get(), 400 INFO_GEN_SOURCE_ARG_DESCRIPTION_LAZY_ATTRIBUTE.get()); 401 lazyAttributeArg.addLongIdentifier("lazy-attribute", true); 402 parser.addArgument(lazyAttributeArg); 403 404 operationalAttributeArg = new StringArgument('O', "operationalAttribute", 405 false, 0, INFO_GEN_SOURCE_VALUE_PLACEHOLDER_NAME.get(), 406 INFO_GEN_SOURCE_ARG_DESCRIPTION_OPERATIONAL_ATTRIBUTE.get()); 407 operationalAttributeArg.addLongIdentifier("operational-attribute", true); 408 parser.addArgument(operationalAttributeArg); 409 410 defaultParentDNArg = new DNArgument('b', "defaultParentDN", false, 1, 411 INFO_GEN_SOURCE_VALUE_PLACEHOLDER_DN.get(), 412 INFO_GEN_SOURCE_ARG_DESCRIPTION_DEFAULT_PARENT_DN.get()); 413 defaultParentDNArg.addLongIdentifier("default-parent-dn", true); 414 parser.addArgument(defaultParentDNArg); 415 416 packageNameArg = new StringArgument('n', "packageName", false, 1, 417 INFO_GEN_SOURCE_VALUE_PLACEHOLDER_NAME.get(), 418 INFO_GEN_SOURCE_ARG_DESCRIPTION_PACKAGE_NAME.get()); 419 packageNameArg.addLongIdentifier("package-name", true); 420 parser.addArgument(packageNameArg); 421 422 classNameArg = new StringArgument('c', "className", false, 1, 423 INFO_GEN_SOURCE_VALUE_PLACEHOLDER_NAME.get(), 424 INFO_GEN_SOURCE_ARG_DESCRIPTION_CLASS_NAME.get()); 425 classNameArg.addLongIdentifier("class-name", true); 426 parser.addArgument(classNameArg); 427 428 terseArg = new BooleanArgument('t', "terse", 1, 429 INFO_GEN_SOURCE_ARG_DESCRIPTION_TERSE.get()); 430 parser.addArgument(terseArg); 431 } 432 433 434 435 /** 436 * {@inheritDoc} 437 */ 438 @Override() 439 public ResultCode doToolProcessing() 440 { 441 // Establish a connection to the target directory server and retrieve the 442 // schema. 443 final LDAPConnection conn; 444 try 445 { 446 conn = getConnection(); 447 } 448 catch (final LDAPException le) 449 { 450 Debug.debugException(le); 451 err(ERR_GEN_SOURCE_CANNOT_CONNECT.get( 452 StaticUtils.getExceptionMessage(le))); 453 return le.getResultCode(); 454 } 455 456 final Schema schema; 457 try 458 { 459 schema = conn.getSchema(); 460 if (schema == null) 461 { 462 err(ERR_GEN_SOURCE_CANNOT_READ_SCHEMA.get( 463 ERR_GEN_SOURCE_SCHEMA_NOT_RETURNED.get())); 464 return ResultCode.NO_RESULTS_RETURNED; 465 } 466 } 467 catch (final LDAPException le) 468 { 469 Debug.debugException(le); 470 err(ERR_GEN_SOURCE_CANNOT_READ_SCHEMA.get( 471 StaticUtils.getExceptionMessage(le))); 472 return le.getResultCode(); 473 } 474 finally 475 { 476 conn.close(); 477 } 478 479 return generateSourceFile(schema, terseArg.isPresent()); 480 } 481 482 483 484 /** 485 * Generates the source file using the information in the provided schema. 486 * 487 * @param schema The schema to use to generate the source file. 488 * @param terse Indicates whether to use terse mode when generating the 489 * source file. If this is {@code true}, then all optional 490 * elements will be omitted from annotations. 491 * 492 * @return A result code obtained for the processing. 493 */ 494 private ResultCode generateSourceFile(final Schema schema, 495 final boolean terse) 496 { 497 // Retrieve and process the structural object class. 498 final TreeMap<String,AttributeTypeDefinition> requiredAttrs = 499 new TreeMap<>(); 500 final TreeMap<String,AttributeTypeDefinition> optionalAttrs = 501 new TreeMap<>(); 502 final TreeMap<String,TreeSet<String>> requiredAttrOCs = new TreeMap<>(); 503 final TreeMap<String,TreeSet<String>> optionalAttrOCs = new TreeMap<>(); 504 final TreeMap<String,String> types = new TreeMap<>(); 505 506 final String structuralClassName = structuralClassArg.getValue(); 507 final ObjectClassDefinition structuralOC = 508 schema.getObjectClass(structuralClassName); 509 if (structuralOC == null) 510 { 511 err(ERR_GEN_SOURCE_STRUCTURAL_CLASS_NOT_FOUND.get(structuralClassName)); 512 return ResultCode.PARAM_ERROR; 513 } 514 515 if (structuralOC.getObjectClassType(schema) != ObjectClassType.STRUCTURAL) 516 { 517 err(ERR_GEN_SOURCE_STRUCTURAL_CLASS_NOT_STRUCTURAL.get( 518 structuralClassName)); 519 return ResultCode.PARAM_ERROR; 520 } 521 522 processObjectClass(structuralOC, schema, requiredAttrs, requiredAttrOCs, 523 optionalAttrs, optionalAttrOCs, types); 524 525 526 // Retrieve and process the auxiliary object classes. 527 final TreeMap<String,ObjectClassDefinition> auxiliaryOCs = new TreeMap<>(); 528 if (auxiliaryClassArg.isPresent()) 529 { 530 for (final String s : auxiliaryClassArg.getValues()) 531 { 532 final ObjectClassDefinition oc = schema.getObjectClass(s); 533 if (oc == null) 534 { 535 err(ERR_GEN_SOURCE_AUXILIARY_CLASS_NOT_FOUND.get(s)); 536 return ResultCode.PARAM_ERROR; 537 } 538 539 if (oc.getObjectClassType(schema) != ObjectClassType.AUXILIARY) 540 { 541 err(ERR_GEN_SOURCE_AUXILIARY_CLASS_NOT_AUXILIARY.get(s)); 542 return ResultCode.PARAM_ERROR; 543 } 544 545 auxiliaryOCs.put(StaticUtils.toLowerCase(s), oc); 546 547 processObjectClass(oc, schema, requiredAttrs, requiredAttrOCs, 548 optionalAttrs, optionalAttrOCs, types); 549 } 550 } 551 552 553 // Determine the appropriate set of superior object classes. 554 final TreeMap<String,ObjectClassDefinition> superiorOCs = new TreeMap<>(); 555 for (final ObjectClassDefinition s : 556 structuralOC.getSuperiorClasses(schema, true)) 557 { 558 superiorOCs.put(StaticUtils.toLowerCase(s.getNameOrOID()), s); 559 } 560 561 for (final ObjectClassDefinition d : auxiliaryOCs.values()) 562 { 563 for (final ObjectClassDefinition s : d.getSuperiorClasses(schema, true)) 564 { 565 superiorOCs.put(StaticUtils.toLowerCase(s.getNameOrOID()), s); 566 } 567 } 568 569 superiorOCs.remove(StaticUtils.toLowerCase(structuralClassName)); 570 for (final String s : auxiliaryOCs.keySet()) 571 { 572 superiorOCs.remove(s); 573 } 574 575 576 // Retrieve and process the operational attributes. 577 final TreeMap<String,AttributeTypeDefinition> operationalAttrs = 578 new TreeMap<>(); 579 if (operationalAttributeArg.isPresent()) 580 { 581 for (final String s : operationalAttributeArg.getValues()) 582 { 583 final AttributeTypeDefinition d = schema.getAttributeType(s); 584 if (d == null) 585 { 586 err(ERR_GEN_SOURCE_OPERATIONAL_ATTRIBUTE_NOT_DEFINED.get(s)); 587 return ResultCode.PARAM_ERROR; 588 } 589 else if (! d.isOperational()) 590 { 591 err(ERR_GEN_SOURCE_OPERATIONAL_ATTRIBUTE_NOT_OPERATIONAL.get(s)); 592 return ResultCode.PARAM_ERROR; 593 } 594 else 595 { 596 final String lowerName = StaticUtils.toLowerCase(s); 597 operationalAttrs.put(lowerName, d); 598 types.put(lowerName, getJavaType(schema, d)); 599 } 600 } 601 } 602 603 604 // Make sure all of the configured RDN attributes are allowed by at least 605 // one of the associated object classes. 606 final TreeSet<String> rdnAttrs = new TreeSet<>(); 607 for (final String s : rdnAttributeArg.getValues()) 608 { 609 final AttributeTypeDefinition d = schema.getAttributeType(s); 610 if (d == null) 611 { 612 err(ERR_GEN_SOURCE_RDN_ATTRIBUTE_NOT_DEFINED.get(s)); 613 return ResultCode.PARAM_ERROR; 614 } 615 616 final String lowerName = StaticUtils.toLowerCase(d.getNameOrOID()); 617 rdnAttrs.add(lowerName); 618 if (requiredAttrs.containsKey(lowerName)) 619 { 620 // No action required. 621 } 622 else if (optionalAttrs.containsKey(lowerName)) 623 { 624 // Move the attribute to the required set. 625 requiredAttrs.put(lowerName, optionalAttrs.remove(lowerName)); 626 requiredAttrOCs.put(lowerName, optionalAttrOCs.remove(lowerName)); 627 } 628 else 629 { 630 err(ERR_GEN_SOURCE_RDN_ATTRIBUTE_NOT_DEFINED.get(s)); 631 return ResultCode.PARAM_ERROR; 632 } 633 } 634 635 636 // Make sure all of the configured lazily-loaded attributes are allowed by 637 // at least one of the associated object classes or matches a configured 638 // operational attribute. 639 final TreeSet<String> lazyAttrs = new TreeSet<>(); 640 for (final String s : lazyAttributeArg.getValues()) 641 { 642 final AttributeTypeDefinition d = schema.getAttributeType(s); 643 if (d == null) 644 { 645 err(ERR_GEN_SOURCE_LAZY_ATTRIBUTE_NOT_DEFINED.get(s)); 646 return ResultCode.PARAM_ERROR; 647 } 648 649 final String lowerName = StaticUtils.toLowerCase(d.getNameOrOID()); 650 lazyAttrs.add(lowerName); 651 if (requiredAttrs.containsKey(lowerName) || 652 optionalAttrs.containsKey(lowerName) || 653 operationalAttrs.containsKey(lowerName)) 654 { 655 // No action required. 656 } 657 else 658 { 659 err(ERR_GEN_SOURCE_LAZY_ATTRIBUTE_NOT_ALLOWED.get(s)); 660 return ResultCode.PARAM_ERROR; 661 } 662 } 663 664 665 final String className; 666 if (classNameArg.isPresent()) 667 { 668 className = classNameArg.getValue(); 669 final StringBuilder invalidReason = new StringBuilder(); 670 if (! PersistUtils.isValidJavaIdentifier(className, invalidReason)) 671 { 672 err(ERR_GEN_SOURCE_INVALID_CLASS_NAME.get(className, 673 invalidReason.toString())); 674 return ResultCode.PARAM_ERROR; 675 } 676 } 677 else 678 { 679 className = StaticUtils.capitalize( 680 PersistUtils.toJavaIdentifier(structuralClassName)); 681 } 682 683 684 final File sourceFile = new File(outputDirectoryArg.getValue(), 685 className + ".java"); 686 final PrintWriter writer; 687 try 688 { 689 writer = new PrintWriter(new FileWriter(sourceFile)); 690 } 691 catch (final Exception e) 692 { 693 Debug.debugException(e); 694 err(ERR_GEN_SOURCE_CANNOT_CREATE_WRITER.get(sourceFile.getAbsolutePath(), 695 StaticUtils.getExceptionMessage(e))); 696 return ResultCode.LOCAL_ERROR; 697 } 698 699 700 if (packageNameArg.isPresent()) 701 { 702 final String packageName = packageNameArg.getValue(); 703 if (! packageName.isEmpty()) 704 { 705 writer.println("package " + packageName + ';'); 706 writer.println(); 707 writer.println(); 708 writer.println(); 709 } 710 } 711 712 boolean javaImports = false; 713 if (needArrays) 714 { 715 writer.println("import " + Arrays.class.getName() + ';'); 716 javaImports = true; 717 } 718 719 if (needDate) 720 { 721 writer.println("import " + Date.class.getName() + ';'); 722 javaImports = true; 723 } 724 725 if (javaImports) 726 { 727 writer.println(); 728 } 729 730 if (needDN) 731 { 732 writer.println("import " + DN.class.getName() + ';'); 733 } 734 735 writer.println("import " + Entry.class.getName() + ';'); 736 writer.println("import " + Filter.class.getName() + ';'); 737 738 if (needDN) 739 { 740 writer.println("import " + LDAPException.class.getName() + ';'); 741 writer.println("import " + LDAPInterface.class.getName() + ';'); 742 } 743 744 writer.println("import " + ReadOnlyEntry.class.getName() + ';'); 745 writer.println("import " + DefaultObjectEncoder.class.getName() + ';'); 746 writer.println("import " + FieldInfo.class.getName() + ';'); 747 writer.println("import " + FilterUsage.class.getName() + ';'); 748 writer.println("import " + LDAPEntryField.class.getName() + ';'); 749 writer.println("import " + LDAPField.class.getName() + ';'); 750 writer.println("import " + LDAPObject.class.getName() + ';'); 751 writer.println("import " + LDAPObjectHandler.class.getName() + ';'); 752 writer.println("import " + LDAPPersister.class.getName() + ';'); 753 writer.println("import " + LDAPPersistException.class.getName() + ';'); 754 755 if (needPersistedObjects) 756 { 757 writer.println("import " + PersistedObjects.class.getName() + ';'); 758 } 759 760 writer.println("import " + PersistFilterType.class.getName() + ';'); 761 762 if (needDN) 763 { 764 writer.println("import " + PersistUtils.class.getName() + ';'); 765 } 766 767 writer.println(); 768 writer.println(); 769 writer.println(); 770 writer.println("/**"); 771 writer.println(" * This class provides an implementation of an object " + 772 "that can be used to"); 773 writer.println(" * represent " + structuralClassName + 774 " objects in the directory."); 775 writer.println(" * It was generated by the " + getToolName() + 776 " tool provided with the"); 777 writer.println(" * UnboundID LDAP SDK for Java. It " + 778 "may be customized as desired to better suit"); 779 writer.println(" * your needs."); 780 writer.println(" */"); 781 writer.println("@LDAPObject(structuralClass=\"" + structuralClassName + 782 "\","); 783 784 switch (auxiliaryOCs.size()) 785 { 786 case 0: 787 // No action required. 788 break; 789 790 case 1: 791 writer.println(" auxiliaryClass=\"" + 792 auxiliaryOCs.values().iterator().next().getNameOrOID() + "\","); 793 break; 794 795 default: 796 final Iterator<ObjectClassDefinition> iterator = 797 auxiliaryOCs.values().iterator(); 798 writer.println(" auxiliaryClass={ \"" + 799 iterator.next().getNameOrOID() + "\","); 800 while (iterator.hasNext()) 801 { 802 final String ocName = iterator.next().getNameOrOID(); 803 if (iterator.hasNext()) 804 { 805 writer.println(" \"" + ocName + 806 "\","); 807 } 808 else 809 { 810 writer.println(" \"" + ocName + 811 "\" },"); 812 } 813 } 814 break; 815 } 816 817 switch (superiorOCs.size()) 818 { 819 case 0: 820 // No action required. 821 break; 822 823 case 1: 824 writer.println(" superiorClass=\"" + 825 superiorOCs.values().iterator().next().getNameOrOID() + "\","); 826 break; 827 828 default: 829 final Iterator<ObjectClassDefinition> iterator = 830 superiorOCs.values().iterator(); 831 writer.println(" superiorClass={ \"" + 832 iterator.next().getNameOrOID() + "\","); 833 while (iterator.hasNext()) 834 { 835 final String ocName = iterator.next().getNameOrOID(); 836 if (iterator.hasNext()) 837 { 838 writer.println(" \"" + ocName + 839 "\","); 840 } 841 else 842 { 843 writer.println(" \"" + ocName + 844 "\" },"); 845 } 846 } 847 break; 848 } 849 850 if (defaultParentDNArg.isPresent()) 851 { 852 writer.println(" defaultParentDN=\"" + 853 defaultParentDNArg.getValue() + "\","); 854 } 855 856 writer.println(" postDecodeMethod=\"doPostDecode\","); 857 writer.println(" postEncodeMethod=\"doPostEncode\")"); 858 writer.println("public class " + className); 859 writer.println("{"); 860 861 if (! terse) 862 { 863 writer.println(" /*"); 864 writer.println(" * NOTE: This class includes a number of annotation " + 865 "elements which are not"); 866 writer.println(" * required but have been provided to make it easier " + 867 "to edit the resulting"); 868 writer.println(" * source code. If you want to exclude these " + 869 "unnecessary annotation"); 870 writer.println(" * elements, use the '--terse' command-line argument."); 871 writer.println(" */"); 872 writer.println(); 873 writer.println(); 874 writer.println(); 875 } 876 877 writer.println(" // The field to use to hold a read-only copy of the " + 878 "associated entry."); 879 writer.println(" @LDAPEntryField()"); 880 writer.println(" private ReadOnlyEntry ldapEntry;"); 881 882 883 // Add all of the fields. First the fields for the RDN attributes, then 884 // for the rest of the required attributes, then for the optional 885 // attributes, and finally any operational attributes. 886 for (final String lowerName : rdnAttrs) 887 { 888 final AttributeTypeDefinition d = requiredAttrs.get(lowerName); 889 final TreeSet<String> ocNames = requiredAttrOCs.get(lowerName); 890 writeField(writer, d, types.get(lowerName), ocNames, true, true, 891 structuralClassName, false, terse); 892 } 893 894 for (final String lowerName : requiredAttrs.keySet()) 895 { 896 if (rdnAttrs.contains(lowerName)) 897 { 898 continue; 899 } 900 901 final AttributeTypeDefinition d = requiredAttrs.get(lowerName); 902 final TreeSet<String> ocNames = requiredAttrOCs.get(lowerName); 903 writeField(writer, d, types.get(lowerName), ocNames, false, true, 904 structuralClassName, lazyAttrs.contains(lowerName), terse); 905 } 906 907 for (final String lowerName : optionalAttrs.keySet()) 908 { 909 final AttributeTypeDefinition d = optionalAttrs.get(lowerName); 910 final TreeSet<String> ocNames = optionalAttrOCs.get(lowerName); 911 writeField(writer, d, types.get(lowerName), ocNames, false, false, 912 structuralClassName, lazyAttrs.contains(lowerName), terse); 913 } 914 915 for (final String lowerName : operationalAttrs.keySet()) 916 { 917 final AttributeTypeDefinition d = operationalAttrs.get(lowerName); 918 final TreeSet<String> ocNames = EMPTY_TREE_SET; 919 writeField(writer, d, types.get(lowerName), ocNames, false, false, 920 structuralClassName, lazyAttrs.contains(lowerName), terse); 921 } 922 923 924 // Add the default constructor. 925 writer.println(); 926 writer.println(); 927 writer.println(); 928 writer.println(" /**"); 929 writer.println(" * Creates a new instance of this object. All fields " + 930 "will be uninitialized,"); 931 writer.println(" * so the setter methods should be used to assign " + 932 "values to them."); 933 writer.println(" */"); 934 writer.println(" public " + className + "()"); 935 writer.println(" {"); 936 writer.println(" // No initialization will be performed by default. " + 937 "Note that if you set"); 938 writer.println(" // values for any fields marked with an @LDAPField, " + 939 "@LDAPDNField, or"); 940 writer.println(" // @LDAPEntryField annotation, they will be " + 941 "overwritten in the course of"); 942 writer.println(" // decoding initializing this object from an LDAP " + 943 "entry."); 944 writer.println(" }"); 945 946 947 // Add a static decode method that can create an instance of the object 948 // from a given entry. 949 writer.println(); 950 writer.println(); 951 writer.println(); 952 writer.println(" /**"); 953 writer.println(" * Creates a new " + className + " object decoded"); 954 writer.println(" * from the provided entry."); 955 writer.println(" *"); 956 writer.println(" * @param entry The entry to be decoded."); 957 writer.println(" *"); 958 writer.println(" * @return The decoded " + className + " object."); 959 writer.println(" *"); 960 writer.println(" * @throws LDAPPersistException If a problem occurs " + 961 "while attempting to"); 962 writer.println(" * decode the provided " + 963 "entry."); 964 writer.println(" */"); 965 writer.println(" public static " + className + 966 " decode(final Entry entry)"); 967 writer.println(" throws LDAPPersistException"); 968 writer.println(" {"); 969 writer.println(" return getPersister().decode(entry);"); 970 writer.println(" }"); 971 972 973 // Add the getPersister method. 974 writer.println(""); 975 writer.println(""); 976 writer.println(""); 977 writer.println(" /**"); 978 writer.println(" * Retrieves an {@code LDAPPersister} instance that " + 979 "may be used to interact"); 980 writer.println(" * with objects of this type."); 981 writer.println(" *"); 982 writer.println(" * @return An {@code LDAPPersister} instance that may " + 983 "be used to interact"); 984 writer.println(" * with objects of this type."); 985 writer.println(" *"); 986 writer.println(" * @throws LDAPPersistException If a problem occurs " + 987 "while creating the"); 988 writer.println(" * " + 989 "{@code LDAPPersister} instance."); 990 writer.println(" */"); 991 writer.println(" public static LDAPPersister<" + className + 992 "> getPersister()"); 993 writer.println(" throws LDAPPersistException"); 994 writer.println(" {"); 995 writer.println(" return LDAPPersister.getInstance(" + className + 996 ".class);"); 997 writer.println(" }"); 998 999 1000 // Add the post-decode and post-encode methods. 1001 writer.println(); 1002 writer.println(); 1003 writer.println(); 1004 writer.println(" /**"); 1005 writer.println(" * Performs any processing that may be necessary after " + 1006 "initializing this"); 1007 writer.println(" * object from an LDAP entry."); 1008 writer.println(" *"); 1009 writer.println(" * @throws LDAPPersistException If there is a " + 1010 "problem with the object after"); 1011 writer.println(" * it has been decoded " + 1012 "from an LDAP entry."); 1013 writer.println(" */"); 1014 writer.println(" private void doPostDecode()"); 1015 writer.println(" throws LDAPPersistException"); 1016 writer.println(" {"); 1017 writer.println(" // No processing is needed by default. You may " + 1018 "provide an implementation"); 1019 writer.println(" // for this method if custom post-decode processing " + 1020 "is needed."); 1021 writer.println(" }"); 1022 writer.println(); 1023 writer.println(); 1024 writer.println(); 1025 writer.println(" /**"); 1026 writer.println(" * Performs any processing that may be necessary after " + 1027 "encoding this object"); 1028 writer.println(" * to an LDAP entry."); 1029 writer.println(" *"); 1030 writer.println(" * @param entry The entry that has been generated. " + 1031 "It may be altered if"); 1032 writer.println(" * desired."); 1033 writer.println(" *"); 1034 writer.println(" * @throws LDAPPersistException If the generated " + 1035 "entry should not be used."); 1036 writer.println(" */"); 1037 writer.println(" private void doPostEncode(final Entry entry)"); 1038 writer.println(" throws LDAPPersistException"); 1039 writer.println(" {"); 1040 writer.println(" // No processing is needed by default. You may " + 1041 "provide an implementation"); 1042 writer.println(" // for this method if custom post-encode processing " + 1043 "is needed."); 1044 writer.println(" }"); 1045 1046 1047 // Add a method for getting a read-only copy of the associated entry. 1048 writer.println(); 1049 writer.println(); 1050 writer.println(); 1051 writer.println(" /**"); 1052 writer.println(" * Retrieves a read-only copy of the entry with which " + 1053 "this object is"); 1054 writer.println(" * associated, if it is available. It will only be " + 1055 "available if this object"); 1056 writer.println(" * was decoded from or encoded to an LDAP entry."); 1057 writer.println(" *"); 1058 writer.println(" * @return A read-only copy of the entry with which " + 1059 "this object is"); 1060 writer.println(" * associated, or {@code null} if it is not " + 1061 "available."); 1062 writer.println(" */"); 1063 writer.println(" public ReadOnlyEntry getLDAPEntry()"); 1064 writer.println(" {"); 1065 writer.println(" return ldapEntry;"); 1066 writer.println(" }"); 1067 1068 1069 // Add a method for getting the DN of the associated entry. 1070 writer.println(); 1071 writer.println(); 1072 writer.println(); 1073 writer.println(" /**"); 1074 writer.println(" * Retrieves the DN of the entry with which this " + 1075 "object is associated, if it"); 1076 writer.println(" * is available. It will only be available if this " + 1077 "object was decoded from or"); 1078 writer.println(" * encoded to an LDAP entry."); 1079 writer.println(" *"); 1080 writer.println(" * @return The DN of the entry with which this object " + 1081 "is associated, or"); 1082 writer.println(" * {@code null} if it is not available."); 1083 writer.println(" */"); 1084 writer.println(" public String getLDAPEntryDN()"); 1085 writer.println(" {"); 1086 writer.println(" if (ldapEntry == null)"); 1087 writer.println(" {"); 1088 writer.println(" return null;"); 1089 writer.println(" }"); 1090 writer.println(" else"); 1091 writer.println(" {"); 1092 writer.println(" return ldapEntry.getDN();"); 1093 writer.println(" }"); 1094 writer.println(" }"); 1095 1096 1097 // Add getter, setter, and filter generation methods for all of the fields 1098 // associated with LDAP attributes. First the fields for the RDN 1099 // attributes, then for the rest of the required attributes, and then for 1100 // the optional attributes. 1101 for (final String lowerName : rdnAttrs) 1102 { 1103 final AttributeTypeDefinition d = requiredAttrs.get(lowerName); 1104 writeFieldMethods(writer, d, types.get(lowerName), true); 1105 } 1106 1107 for (final String lowerName : requiredAttrs.keySet()) 1108 { 1109 if (rdnAttrs.contains(lowerName)) 1110 { 1111 continue; 1112 } 1113 1114 final AttributeTypeDefinition d = requiredAttrs.get(lowerName); 1115 writeFieldMethods(writer, d, types.get(lowerName), true); 1116 } 1117 1118 for (final String lowerName : optionalAttrs.keySet()) 1119 { 1120 final AttributeTypeDefinition d = optionalAttrs.get(lowerName); 1121 writeFieldMethods(writer, d, types.get(lowerName), true); 1122 } 1123 1124 for (final String lowerName : operationalAttrs.keySet()) 1125 { 1126 final AttributeTypeDefinition d = operationalAttrs.get(lowerName); 1127 writeFieldMethods(writer, d, types.get(lowerName), false); 1128 } 1129 1130 writeToString(writer, className, requiredAttrs.values(), 1131 optionalAttrs.values(), operationalAttrs.values()); 1132 1133 writer.println("}"); 1134 writer.println(); 1135 writer.close(); 1136 1137 return ResultCode.SUCCESS; 1138 } 1139 1140 1141 1142 /** 1143 * Performs an appropriate set of processing for the provided object class to 1144 * ensure that all of the required and optional attributes are classified 1145 * properly. 1146 * 1147 * @param oc The object class to process. 1148 * @param s The server schema. 1149 * @param ra The set of required attributes identified so far. 1150 * @param rac The object classes referenced by the required attributes. 1151 * @param oa The set of optional attributes identified so far. 1152 * @param oac The object classes referenced by the optional attributes. 1153 * @param t A map of attribute type names to Java types. 1154 */ 1155 private void processObjectClass(final ObjectClassDefinition oc, 1156 final Schema s, 1157 final TreeMap<String,AttributeTypeDefinition> ra, 1158 final TreeMap<String,TreeSet<String>> rac, 1159 final TreeMap<String,AttributeTypeDefinition> oa, 1160 final TreeMap<String,TreeSet<String>> oac, 1161 final TreeMap<String,String> t) 1162 { 1163 for (final AttributeTypeDefinition d : oc.getRequiredAttributes(s, true)) 1164 { 1165 if (d.hasNameOrOID("objectClass")) 1166 { 1167 continue; 1168 } 1169 1170 final String lowerName = StaticUtils.toLowerCase(d.getNameOrOID()); 1171 if (ra.containsKey(lowerName)) 1172 { 1173 rac.get(lowerName).add(oc.getNameOrOID()); 1174 } 1175 else if (oa.containsKey(lowerName)) 1176 { 1177 oa.remove(lowerName); 1178 ra.put(lowerName, d); 1179 1180 final TreeSet<String> ocSet = oac.remove(lowerName); 1181 ocSet.add(oc.getNameOrOID()); 1182 rac.put(lowerName, ocSet); 1183 } 1184 else 1185 { 1186 final TreeSet<String> ocSet = new TreeSet<>(); 1187 ocSet.add(oc.getNameOrOID()); 1188 ra.put(lowerName, d); 1189 rac.put(lowerName, ocSet); 1190 t.put(lowerName, getJavaType(s, d)); 1191 } 1192 } 1193 1194 for (final AttributeTypeDefinition d : oc.getOptionalAttributes(s, true)) 1195 { 1196 if (d.hasNameOrOID("objectClass")) 1197 { 1198 continue; 1199 } 1200 1201 final String lowerName = StaticUtils.toLowerCase(d.getNameOrOID()); 1202 if (ra.containsKey(lowerName)) 1203 { 1204 rac.get(lowerName).add(oc.getNameOrOID()); 1205 } 1206 else if (oa.containsKey(lowerName)) 1207 { 1208 oac.get(lowerName).add(oc.getNameOrOID()); 1209 } 1210 else 1211 { 1212 final TreeSet<String> ocSet = new TreeSet<>(); 1213 ocSet.add(oc.getNameOrOID()); 1214 oa.put(lowerName, d); 1215 oac.put(lowerName, ocSet); 1216 t.put(lowerName, getJavaType(s, d)); 1217 } 1218 } 1219 } 1220 1221 1222 1223 /** 1224 * Writes information about a field to the Java class file. 1225 * 1226 * @param writer The writer to which the field information should be 1227 * written. 1228 * @param d The attribute type definition. 1229 * @param type The name of the Java type to use for the field. 1230 * @param ocNames The names of the object classes for the attribute type. 1231 * @param inRDN Indicates whether the attribute should be included in 1232 * generated entry RDNs. 1233 * @param required Indicates whether the attribute should be considered 1234 * required. 1235 * @param sc The name of the structural object class for the object. 1236 * @param lazy Indicates whether the field should be marked for lazy 1237 * loading. 1238 * @param terse Indicates whether to use terse mode. 1239 */ 1240 private static void writeField(final PrintWriter writer, 1241 final AttributeTypeDefinition d, final String type, 1242 final TreeSet<String> ocNames, 1243 final boolean inRDN, final boolean required, 1244 final String sc, final boolean lazy, 1245 final boolean terse) 1246 { 1247 final String attrName = d.getNameOrOID(); 1248 final String fieldName = PersistUtils.toJavaIdentifier(attrName); 1249 1250 writer.println(); 1251 1252 if (inRDN) 1253 { 1254 writer.println(" // The field used for RDN attribute " + attrName + '.'); 1255 } 1256 else if (required) 1257 { 1258 writer.println(" // The field used for required attribute " + attrName + 1259 '.'); 1260 } 1261 else if (d.isOperational()) 1262 { 1263 writer.println(" // The field used for operational attribute " + 1264 attrName + '.'); 1265 } 1266 else 1267 { 1268 writer.println(" // The field used for optional attribute " + attrName + 1269 '.'); 1270 } 1271 1272 boolean added = false; 1273 if (terse && attrName.equalsIgnoreCase(fieldName)) 1274 { 1275 writer.print(" @LDAPField("); 1276 } 1277 else 1278 { 1279 writer.print(" @LDAPField(attribute=\"" + attrName + '"'); 1280 added = true; 1281 } 1282 1283 if (ocNames.isEmpty()) 1284 { 1285 // Don't need to do anything. This should only be the case for 1286 // operational attributes. 1287 } 1288 else if (ocNames.size() == 1) 1289 { 1290 if ((! terse) || (! ocNames.iterator().next().equalsIgnoreCase(sc))) 1291 { 1292 if (added) 1293 { 1294 writer.println(","); 1295 writer.print(" objectClass=\"" + 1296 ocNames.iterator().next() + '"'); 1297 } 1298 else 1299 { 1300 writer.println("objectClass=\"" + 1301 ocNames.iterator().next() + '"'); 1302 added = true; 1303 } 1304 } 1305 } 1306 else 1307 { 1308 final Iterator<String> iterator = ocNames.iterator(); 1309 if (added) 1310 { 1311 writer.println(","); 1312 writer.println(" objectClass={ \"" + 1313 iterator.next() + "\","); 1314 } 1315 else 1316 { 1317 writer.println("objectClass={ \"" + 1318 iterator.next() + "\","); 1319 added = true; 1320 } 1321 1322 while (iterator.hasNext()) 1323 { 1324 final String name = iterator.next(); 1325 if (iterator.hasNext()) 1326 { 1327 writer.println(" \"" + name + "\","); 1328 } 1329 else 1330 { 1331 writer.print(" \"" + name + "\" }"); 1332 } 1333 } 1334 } 1335 1336 if (inRDN) 1337 { 1338 if (added) 1339 { 1340 writer.println(","); 1341 writer.println(" inRDN=true,"); 1342 } 1343 else 1344 { 1345 writer.println("inRDN=true,"); 1346 added = true; 1347 } 1348 writer.print(" filterUsage=FilterUsage.ALWAYS_ALLOWED"); 1349 } 1350 else 1351 { 1352 if (! terse) 1353 { 1354 if (added) 1355 { 1356 writer.println(","); 1357 writer.print(" " + 1358 "filterUsage=FilterUsage.CONDITIONALLY_ALLOWED"); 1359 } 1360 else 1361 { 1362 writer.print("filterUsage=FilterUsage.CONDITIONALLY_ALLOWED"); 1363 added = true; 1364 } 1365 } 1366 } 1367 1368 if (required) 1369 { 1370 if (added) 1371 { 1372 writer.println(","); 1373 writer.print(" requiredForEncode=true"); 1374 } 1375 else 1376 { 1377 writer.print("requiredForEncode=true"); 1378 added = true; 1379 } 1380 } 1381 1382 if (d.isOperational()) 1383 { 1384 if (added) 1385 { 1386 writer.println(","); 1387 writer.println(" inAdd=false,"); 1388 } 1389 else 1390 { 1391 writer.println("inAdd=false,"); 1392 added = true; 1393 } 1394 1395 writer.print(" inModify=false"); 1396 } 1397 1398 if (lazy) 1399 { 1400 if (added) 1401 { 1402 writer.println(","); 1403 writer.print(" lazilyLoad=true"); 1404 } 1405 else 1406 { 1407 writer.print("lazilyLoad=true"); 1408 added = true; 1409 } 1410 } 1411 1412 writer.println(")"); 1413 if (d.isSingleValued()) 1414 { 1415 writer.println(" private " + type + ' ' + fieldName + ';'); 1416 } 1417 else 1418 { 1419 writer.println(" private " + type + "[] " + fieldName + ';'); 1420 } 1421 } 1422 1423 1424 1425 /** 1426 * Writes getter, setter, and filter creation methods for the specified 1427 * attribute. 1428 * 1429 * @param writer The writer to use to write the methods. 1430 * @param d The attribute type definition to be written. 1431 * @param type The name of the Java type to use for the attribute. 1432 * @param addSetter Indicates whether to write a setter method. 1433 */ 1434 private static void writeFieldMethods(final PrintWriter writer, 1435 final AttributeTypeDefinition d, 1436 final String type, 1437 final boolean addSetter) 1438 { 1439 writer.println(); 1440 writer.println(); 1441 writer.println(); 1442 1443 final String attrName = d.getNameOrOID(); 1444 final String fieldName = PersistUtils.toJavaIdentifier(attrName); 1445 final String capFieldName = StaticUtils.capitalize(fieldName); 1446 1447 if (d.isSingleValued()) 1448 { 1449 if (type.equals("DN")) 1450 { 1451 writer.println(" /**"); 1452 writer.println(" * Retrieves the first value for the field " + 1453 "associated with the"); 1454 writer.println(" * " + attrName + " attribute as a DN, if present."); 1455 writer.println(" *"); 1456 writer.println(" * @return The first value for the field " + 1457 "associated with the"); 1458 writer.println(" * " + attrName + " attribute, or"); 1459 writer.println(" * {@code null} if the field does not " + 1460 "have a value."); 1461 writer.println(" */"); 1462 writer.println(" public DN get" + capFieldName + "DN()"); 1463 writer.println(" {"); 1464 writer.println(" return " + fieldName + ';'); 1465 writer.println(" }"); 1466 1467 writer.println(); 1468 writer.println(); 1469 writer.println(); 1470 1471 writer.println(" /**"); 1472 writer.println(" * Retrieves the object referenced by the DN held " + 1473 "in the"); 1474 writer.println(" * " + attrName + " attribute, if present."); 1475 writer.println(" *"); 1476 writer.println(" * @param <T> The type of object to return."); 1477 writer.println(" *"); 1478 writer.println(" * @param connection The connection to use to " + 1479 "retrieve the entry. It must"); 1480 writer.println(" * not be {@code null}."); 1481 writer.println(" * @param type The type of object as which " + 1482 "to decode the entry. It"); 1483 writer.println(" * must not be {@code null}, " + 1484 "and the class must be marked"); 1485 writer.println(" * with the {@code LDAPObject} " + 1486 "annotation type."); 1487 writer.println(" *"); 1488 writer.println(" * @return The object decoded from the entry with " + 1489 "the associated DN, or"); 1490 writer.println(" * {@code null} if the field does not " + 1491 "have a value or the referenced"); 1492 writer.println(" * entry does not exist."); 1493 writer.println(" *"); 1494 writer.println(" * @throws LDAPException If a problem occurs " + 1495 "while attempting to retrieve"); 1496 writer.println(" * the entry or decode it " + 1497 "as an object of the"); 1498 writer.println(" * specified type."); 1499 writer.println(" */"); 1500 writer.println(" public <T> T get" + capFieldName + "Object("); 1501 writer.println(" final LDAPInterface connection,"); 1502 writer.println(" final Class<T> type)"); 1503 writer.println(" throws LDAPException"); 1504 writer.println(" {"); 1505 writer.println(" return PersistUtils.getEntryAsObject(" + fieldName + 1506 ','); 1507 writer.println(" type, connection);"); 1508 writer.println(" }"); 1509 1510 if (addSetter) 1511 { 1512 writer.println(); 1513 writer.println(); 1514 writer.println(); 1515 1516 writer.println(" /**"); 1517 writer.println(" * Sets the value for the field associated with " + 1518 "the"); 1519 writer.println(" * " + attrName + " attribute."); 1520 writer.println(" *"); 1521 writer.println(" * @param v The value for the field associated " + 1522 "with the"); 1523 writer.println(" * " + attrName + " attribute."); 1524 writer.println(" */"); 1525 writer.println(" public void set" + capFieldName + "(final DN v)"); 1526 writer.println(" {"); 1527 writer.println(" this." + fieldName + " = v;"); 1528 writer.println(" }"); 1529 1530 writer.println(); 1531 writer.println(); 1532 writer.println(); 1533 1534 writer.println(" /**"); 1535 writer.println(" * Sets the value for the field associated with " + 1536 "the"); 1537 writer.println(" * " + attrName + " attribute."); 1538 writer.println(" *"); 1539 writer.println(" * @param v The string representation of the " + 1540 "value for the field associated"); 1541 writer.println(" * with the " + attrName + 1542 " attribute."); 1543 writer.println(" *"); 1544 writer.println(" * @throws LDAPException If the provided " + 1545 "string cannot be parsed as a DN."); 1546 writer.println(" */"); 1547 writer.println(" public void set" + capFieldName + 1548 "(final String v)"); 1549 writer.println(" throws LDAPException"); 1550 writer.println(" {"); 1551 writer.println(" if (v == null)"); 1552 writer.println(" {"); 1553 writer.println(" this." + fieldName + " = null;"); 1554 writer.println(" }"); 1555 writer.println(" else"); 1556 writer.println(" {"); 1557 writer.println(" this." + fieldName + " = new DN(v);"); 1558 writer.println(" }"); 1559 writer.println(" }"); 1560 } 1561 } 1562 else 1563 { 1564 writer.println(" /**"); 1565 writer.println(" * Retrieves the value for the field associated " + 1566 "with the"); 1567 writer.println(" * " + attrName + " attribute, if present."); 1568 writer.println(" *"); 1569 writer.println(" * @return The value for the field associated " + 1570 "with the"); 1571 writer.println(" * " + attrName + " attribute, or"); 1572 writer.println(" * {@code null} if the field does not " + 1573 "have a value."); 1574 writer.println(" */"); 1575 writer.println(" public " + type + " get" + capFieldName + "()"); 1576 writer.println(" {"); 1577 writer.println(" return " + fieldName + ';'); 1578 writer.println(" }"); 1579 1580 if (addSetter) 1581 { 1582 writer.println(); 1583 writer.println(); 1584 writer.println(); 1585 1586 writer.println(" /**"); 1587 writer.println(" * Sets the value for the field associated with " + 1588 "the"); 1589 writer.println(" * " + attrName + " attribute."); 1590 writer.println(" *"); 1591 writer.println(" * @param v The value for the field associated " + 1592 "with the"); 1593 writer.println(" * " + attrName + " attribute."); 1594 writer.println(" */"); 1595 writer.println(" public void set" + capFieldName + "(final " + type + 1596 " v)"); 1597 writer.println(" {"); 1598 writer.println(" this." + fieldName + " = v;"); 1599 writer.println(" }"); 1600 } 1601 } 1602 } 1603 else 1604 { 1605 if (type.equals("DN")) 1606 { 1607 writer.println(" /**"); 1608 writer.println(" * Retrieves the first value for the field " + 1609 "associated with the"); 1610 writer.println(" * " + attrName + " attribute as a DN, if present."); 1611 writer.println(" *"); 1612 writer.println(" * @return The first value for the field " + 1613 "associated with the"); 1614 writer.println(" * " + attrName + " attribute, or"); 1615 writer.println(" * {@code null} if that attribute was not " + 1616 "present in the entry or"); 1617 writer.println(" * does not have any values."); 1618 writer.println(" */"); 1619 writer.println(" public DN getFirst" + capFieldName + "DN()"); 1620 writer.println(" {"); 1621 writer.println(" if ((" + fieldName + " == null) ||"); 1622 writer.println(" (" + fieldName + ".length == 0))"); 1623 writer.println(" {"); 1624 writer.println(" return null;"); 1625 writer.println(" }"); 1626 writer.println(" else"); 1627 writer.println(" {"); 1628 writer.println(" return " + fieldName + "[0];"); 1629 writer.println(" }"); 1630 writer.println(" }"); 1631 1632 writer.println(); 1633 writer.println(); 1634 writer.println(); 1635 1636 writer.println(" /**"); 1637 writer.println(" * Retrieves the values for the field associated " + 1638 "with the"); 1639 writer.println(" * " + attrName + " attribute as DNs, if present."); 1640 writer.println(" *"); 1641 writer.println(" * @return The values for the field associated " + 1642 "with the"); 1643 writer.println(" * " + attrName + " attribute, or"); 1644 writer.println(" * {@code null} if that attribute was not " + 1645 "present in the entry."); 1646 writer.println(" */"); 1647 writer.println(" public DN[] get" + capFieldName + "DNs()"); 1648 writer.println(" {"); 1649 writer.println(" return " + fieldName + ';'); 1650 writer.println(" }"); 1651 1652 writer.println(); 1653 writer.println(); 1654 writer.println(); 1655 1656 writer.println(" /**"); 1657 writer.println(" * Retrieves the values for the field associated " + 1658 "with the"); 1659 writer.println(" * " + attrName + " attribute as objects of the " + 1660 "specified type,"); 1661 writer.println(" * if present."); 1662 writer.println(" *"); 1663 writer.println(" * @param <T> The type of object to return."); 1664 writer.println(" *"); 1665 writer.println(" * @param connection The connection to use to " + 1666 "retrieve the entries. It"); 1667 writer.println(" * must not be {@code null}."); 1668 writer.println(" * @param type The type of object as which " + 1669 "the entries should be"); 1670 writer.println(" * decoded. It must not be " + 1671 "{@code null}, and the class"); 1672 writer.println(" * must be marked with the " + 1673 "{@code LDAPObject} annotation"); 1674 writer.println(" * type."); 1675 writer.println(" *"); 1676 writer.println(" * @return A {@code PersistedObjects} object that " + 1677 "may be used to iterate"); 1678 writer.println(" * across the resulting objects."); 1679 writer.println(" *"); 1680 writer.println(" * @throws LDAPException If the requested type " + 1681 "cannot be used with the LDAP"); 1682 writer.println(" * SDK persistence " + 1683 "framework."); 1684 writer.println(" */"); 1685 writer.println(" public <T> PersistedObjects<T> get" + capFieldName + 1686 "Objects("); 1687 writer.println(" final " + 1688 "LDAPInterface connection,"); 1689 writer.println(" final Class<T> " + 1690 "type)"); 1691 writer.println(" throws LDAPException"); 1692 writer.println(" {"); 1693 writer.println(" return PersistUtils.getEntriesAsObjects(" + 1694 fieldName + ','); 1695 writer.println(" type, connection);"); 1696 writer.println(" }"); 1697 1698 if (addSetter) 1699 { 1700 writer.println(); 1701 writer.println(); 1702 writer.println(); 1703 1704 writer.println(" /**"); 1705 writer.println(" * Sets the values for the field associated with " + 1706 "the"); 1707 writer.println(" * " + attrName + " attribute."); 1708 writer.println(" *"); 1709 writer.println(" * @param v The values for the field " + 1710 "associated with the"); 1711 writer.println(" * " + attrName + " attribute."); 1712 writer.println(" */"); 1713 writer.println(" public void set" + capFieldName + 1714 "(final DN... v)"); 1715 writer.println(" {"); 1716 writer.println(" this." + fieldName + " = v;"); 1717 writer.println(" }"); 1718 1719 writer.println(); 1720 writer.println(); 1721 writer.println(); 1722 1723 writer.println(" /**"); 1724 writer.println(" * Sets the values for the field associated with " + 1725 "the"); 1726 writer.println(" * " + attrName + " attribute."); 1727 writer.println(" *"); 1728 writer.println(" * @param v The string representations of the " + 1729 "values for the field"); 1730 writer.println(" * associated with the " + attrName + 1731 " attribute."); 1732 writer.println(" *"); 1733 writer.println(" * @throws LDAPException If any of the " + 1734 "provided strings cannot be parsed as"); 1735 writer.println(" * a DN."); 1736 writer.println(" */"); 1737 writer.println(" public void set" + capFieldName + 1738 "(final String... v)"); 1739 writer.println(" throws LDAPException"); 1740 writer.println(" {"); 1741 writer.println(" if (v == null)"); 1742 writer.println(" {"); 1743 writer.println(" this." + fieldName + " = null;"); 1744 writer.println(" }"); 1745 writer.println(" else"); 1746 writer.println(" {"); 1747 writer.println(" this." + fieldName + " = new DN[v.length];"); 1748 writer.println(" for (int i=0; i < v.length; i++)"); 1749 writer.println(" {"); 1750 writer.println(" this." + fieldName + "[i] = new DN(v[i]);"); 1751 writer.println(" }"); 1752 writer.println(" }"); 1753 writer.println(" }"); 1754 } 1755 } 1756 else 1757 { 1758 writer.println(" /**"); 1759 writer.println(" * Retrieves the first value for the field " + 1760 "associated with the"); 1761 writer.println(" * " + attrName + " attribute, if present."); 1762 writer.println(" *"); 1763 writer.println(" * @return The first value for the field " + 1764 "associated with the"); 1765 writer.println(" * " + attrName + " attribute, or"); 1766 writer.println(" * {@code null} if that attribute was not " + 1767 "present in the entry or"); 1768 writer.println(" * does not have any values."); 1769 writer.println(" */"); 1770 writer.println(" public " + type + " getFirst" + capFieldName + "()"); 1771 writer.println(" {"); 1772 writer.println(" if ((" + fieldName + " == null) ||"); 1773 writer.println(" (" + fieldName + ".length == 0))"); 1774 writer.println(" {"); 1775 writer.println(" return null;"); 1776 writer.println(" }"); 1777 writer.println(" else"); 1778 writer.println(" {"); 1779 writer.println(" return " + fieldName + "[0];"); 1780 writer.println(" }"); 1781 writer.println(" }"); 1782 1783 writer.println(); 1784 writer.println(); 1785 writer.println(); 1786 1787 writer.println(" /**"); 1788 writer.println(" * Retrieves the values for the field associated " + 1789 "with the"); 1790 writer.println(" * " + attrName + " attribute, if present."); 1791 writer.println(" *"); 1792 writer.println(" * @return The values for the field associated " + 1793 "with the"); 1794 writer.println(" * " + attrName + " attribute, or"); 1795 writer.println(" * {@code null} if that attribute was not " + 1796 "present in the entry."); 1797 writer.println(" */"); 1798 writer.println(" public " + type + "[] get" + capFieldName + "()"); 1799 writer.println(" {"); 1800 writer.println(" return " + fieldName + ';'); 1801 writer.println(" }"); 1802 1803 if (addSetter) 1804 { 1805 writer.println(); 1806 writer.println(); 1807 writer.println(); 1808 1809 writer.println(" /**"); 1810 writer.println(" * Sets the values for the field associated with " + 1811 "the"); 1812 writer.println(" * " + attrName + " attribute."); 1813 writer.println(" *"); 1814 writer.println(" * @param v The values for the field " + 1815 "associated with the"); 1816 writer.println(" * " + attrName + " attribute."); 1817 writer.println(" */"); 1818 writer.println(" public void set" + capFieldName + "(final " + type + 1819 "... v)"); 1820 writer.println(" {"); 1821 writer.println(" this." + fieldName + " = v;"); 1822 writer.println(" }"); 1823 } 1824 } 1825 } 1826 1827 1828 writer.println(); 1829 writer.println(); 1830 writer.println(); 1831 1832 writer.println(" /**"); 1833 writer.println(" * Generates a filter that may be used to search for " + 1834 "objects of this type"); 1835 writer.println(" * using the " + attrName + " attribute."); 1836 writer.println(" * The resulting filter may be combined with other " + 1837 "filter elements to create a"); 1838 writer.println(" * more complex filter."); 1839 writer.println(" *"); 1840 writer.println(" * @param filterType The type of filter to generate."); 1841 writer.println(" * @param value The value to use to use for the " + 1842 "filter. It may be"); 1843 writer.println(" * {@code null} only for a filter " + 1844 "type of"); 1845 writer.println(" * {@code PRESENCE}."); 1846 writer.println(" *"); 1847 writer.println(" * @return The generated search filter."); 1848 writer.println(" *"); 1849 writer.println(" * @throws LDAPPersistException If a problem is " + 1850 "encountered while attempting"); 1851 writer.println(" * to generate the " + 1852 "filter."); 1853 writer.println(" */"); 1854 writer.println(" public static Filter generate" + capFieldName + 1855 "Filter("); 1856 writer.println(" final PersistFilterType " + 1857 "filterType,"); 1858 writer.println(" final " + type + " value)"); 1859 writer.println(" throws LDAPPersistException"); 1860 writer.println(" {"); 1861 writer.println(" final byte[] valueBytes;"); 1862 writer.println(" if (filterType == PersistFilterType.PRESENCE)"); 1863 writer.println(" {"); 1864 writer.println(" valueBytes = null;"); 1865 writer.println(" }"); 1866 writer.println(" else"); 1867 writer.println(" {"); 1868 writer.println(" if (value == null)"); 1869 writer.println(" {"); 1870 writer.println(" throw new LDAPPersistException(\"Unable to " + 1871 "generate a filter of type \" +"); 1872 writer.println(" filterType.name() + \" with a null value " + 1873 "for attribute \" +"); 1874 writer.println(" \"" + attrName + "\");"); 1875 writer.println(" }"); 1876 writer.println(); 1877 writer.println(" final LDAPObjectHandler<?> objectHandler ="); 1878 writer.println(" getPersister().getObjectHandler();"); 1879 writer.println(" final FieldInfo fieldInfo = " + 1880 "objectHandler.getFields().get("); 1881 writer.println(" \"" + StaticUtils.toLowerCase(attrName) + 1882 "\");"); 1883 writer.println(); 1884 writer.println(" final DefaultObjectEncoder objectEncoder = new " + 1885 "DefaultObjectEncoder();"); 1886 writer.println(" valueBytes = " + 1887 "objectEncoder.encodeFieldValue(fieldInfo.getField(),"); 1888 1889 if (d.isSingleValued()) 1890 { 1891 writer.println(" value,"); 1892 } 1893 else 1894 { 1895 writer.println(" new " + type + "[] { value },"); 1896 } 1897 1898 writer.println(" \"" + attrName + "\").getValueByteArray();"); 1899 writer.println(" }"); 1900 writer.println(); 1901 writer.println(" switch (filterType)"); 1902 writer.println(" {"); 1903 writer.println(" case PRESENCE:"); 1904 writer.println(" return Filter.createPresenceFilter("); 1905 writer.println(" \"" + attrName + "\");"); 1906 writer.println(" case EQUALITY:"); 1907 writer.println(" return Filter.createEqualityFilter("); 1908 writer.println(" \"" + attrName + "\","); 1909 writer.println(" valueBytes);"); 1910 writer.println(" case STARTS_WITH:"); 1911 writer.println(" return Filter.createSubstringFilter("); 1912 writer.println(" \"" + attrName + "\","); 1913 writer.println(" valueBytes, null, null);"); 1914 writer.println(" case ENDS_WITH:"); 1915 writer.println(" return Filter.createSubstringFilter("); 1916 writer.println(" \"" + attrName + "\","); 1917 writer.println(" null, null, valueBytes);"); 1918 writer.println(" case CONTAINS:"); 1919 writer.println(" return Filter.createSubstringFilter("); 1920 writer.println(" \"" + attrName + "\","); 1921 writer.println(" null, new byte[][] { valueBytes }, null);"); 1922 writer.println(" case GREATER_OR_EQUAL:"); 1923 writer.println(" return Filter.createGreaterOrEqualFilter("); 1924 writer.println(" \"" + attrName + "\","); 1925 writer.println(" valueBytes);"); 1926 writer.println(" case LESS_OR_EQUAL:"); 1927 writer.println(" return Filter.createLessOrEqualFilter("); 1928 writer.println(" \"" + attrName + "\","); 1929 writer.println(" valueBytes);"); 1930 writer.println(" case APPROXIMATELY_EQUAL_TO:"); 1931 writer.println(" return Filter.createApproximateMatchFilter("); 1932 writer.println(" \"" + attrName + "\","); 1933 writer.println(" valueBytes);"); 1934 writer.println(" default:"); 1935 writer.println(" // This should never happen."); 1936 writer.println(" throw new LDAPPersistException(\"Unrecognized " + 1937 "filter type \" +"); 1938 writer.println(" filterType.name());"); 1939 writer.println(" }"); 1940 writer.println(" }"); 1941 } 1942 1943 1944 1945 /** 1946 * Writes a {@code toString} method for the generated class. 1947 * 1948 * @param writer The writer to use to write the methods. 1949 * @param className The base name (without package information) for 1950 * the generated class. 1951 * @param requiredAttrs The set of required attributes for the generated 1952 * class. 1953 * @param optionalAttrs The set of optional attributes for the generated 1954 * class. 1955 * @param operationalAttrs The set of operational attributes for the 1956 * generated class. 1957 */ 1958 private static void writeToString(final PrintWriter writer, 1959 final String className, 1960 final Collection<AttributeTypeDefinition> requiredAttrs, 1961 final Collection<AttributeTypeDefinition> optionalAttrs, 1962 final Collection<AttributeTypeDefinition> operationalAttrs) 1963 { 1964 writer.println(); 1965 writer.println(); 1966 writer.println(); 1967 writer.println(" /**"); 1968 writer.println(" * Retrieves a string representation of this"); 1969 writer.println(" * {@code " + className + "} object."); 1970 writer.println(" *"); 1971 writer.println(" * @return A string representation of this"); 1972 writer.println(" * {@code " + className + "} object."); 1973 writer.println(" */"); 1974 writer.println(" @Override()"); 1975 writer.println(" public String toString()"); 1976 writer.println(" {"); 1977 writer.println(" final StringBuilder buffer = new StringBuilder();"); 1978 writer.println(" toString(buffer);"); 1979 writer.println(" return buffer.toString();"); 1980 writer.println(" }"); 1981 1982 writer.println(); 1983 writer.println(); 1984 writer.println(); 1985 writer.println(" /**"); 1986 writer.println(" * Appends a string representation of this"); 1987 writer.println(" * {@code " + className + "} object"); 1988 writer.println(" * to the provided buffer."); 1989 writer.println(" *"); 1990 writer.println(" * @param buffer The buffer to which the string " + 1991 "representation should be"); 1992 writer.println(" * appended."); 1993 writer.println(" */"); 1994 writer.println(" public void toString(final StringBuilder buffer)"); 1995 writer.println(" {"); 1996 writer.println(" buffer.append(\"" + className + "(\");"); 1997 writer.println(); 1998 writer.println(" boolean appended = false;"); 1999 writer.println(" if (ldapEntry != null)"); 2000 writer.println(" {"); 2001 writer.println(" appended = true;"); 2002 writer.println(" buffer.append(\"entryDN='\");"); 2003 writer.println(" buffer.append(ldapEntry.getDN());"); 2004 writer.println(" buffer.append('\\'');"); 2005 writer.println(" }"); 2006 2007 for (final AttributeTypeDefinition d : requiredAttrs) 2008 { 2009 writeToStringField(writer, d); 2010 } 2011 2012 for (final AttributeTypeDefinition d : optionalAttrs) 2013 { 2014 writeToStringField(writer, d); 2015 } 2016 2017 for (final AttributeTypeDefinition d : operationalAttrs) 2018 { 2019 writeToStringField(writer, d); 2020 } 2021 2022 writer.println(); 2023 writer.println(" buffer.append(')');"); 2024 writer.println(" }"); 2025 } 2026 2027 2028 2029 /** 2030 * Writes information about the provided field for use in the {@code toString} 2031 * method. 2032 * 2033 * @param w The writer to use to write the {@code toString} content. 2034 * @param d The attribute type definition for the field to write. 2035 */ 2036 private static void writeToStringField(final PrintWriter w, 2037 final AttributeTypeDefinition d) 2038 { 2039 final String fieldName = PersistUtils.toJavaIdentifier(d.getNameOrOID()); 2040 w.println(); 2041 w.println(" if (" + fieldName + " != null)"); 2042 w.println(" {"); 2043 w.println(" if (appended)"); 2044 w.println(" {"); 2045 w.println(" buffer.append(\", \");"); 2046 w.println(" }"); 2047 w.println(" appended = true;"); 2048 w.println(" buffer.append(\"" + fieldName + "=\");"); 2049 if (d.isSingleValued()) 2050 { 2051 w.println(" buffer.append(" + fieldName + ");"); 2052 } 2053 else 2054 { 2055 w.println(" buffer.append(Arrays.toString(" + fieldName + "));"); 2056 } 2057 w.println(" }"); 2058 } 2059 2060 2061 2062 /** 2063 * Retrieves the Java type to use for the provided attribute type definition. 2064 * For multi-valued attributes, the value returned will be the base type 2065 * without square brackets to indicate an array. 2066 * 2067 * @param schema The schema to use to determine the syntax for the 2068 * attribute. 2069 * @param d The attribute type definition for which to get the Java 2070 * type. 2071 * 2072 * @return The Java type to use for the provided attribute type definition. 2073 */ 2074 private String getJavaType(final Schema schema, 2075 final AttributeTypeDefinition d) 2076 { 2077 if (! d.isSingleValued()) 2078 { 2079 needArrays = true; 2080 } 2081 2082 final String syntaxOID = d.getSyntaxOID(schema); 2083 if (syntaxOID == null) 2084 { 2085 return "String"; 2086 } 2087 2088 final String oid; 2089 final int bracePos = syntaxOID.indexOf('{'); 2090 if (bracePos > 0) 2091 { 2092 oid = syntaxOID.substring(0, bracePos); 2093 } 2094 else 2095 { 2096 oid = syntaxOID; 2097 } 2098 2099 if (oid.equals("1.3.6.1.4.1.1466.115.121.1.7")) 2100 { 2101 // Boolean 2102 return "Boolean"; 2103 } 2104 else if (oid.equals("1.3.6.1.4.1.4203.1.1.2") || 2105 oid.equals("1.3.6.1.4.1.1466.115.121.1.5") || 2106 oid.equals("1.3.6.1.4.1.1466.115.121.1.8") || 2107 oid.equals("1.3.6.1.4.1.1466.115.121.1.9") || 2108 oid.equals("1.3.6.1.4.1.1466.115.121.1.10") || 2109 oid.equals("1.3.6.1.4.1.1466.115.121.1.28") || 2110 oid.equals("1.3.6.1.4.1.1466.115.121.1.40")) 2111 { 2112 // auth password 2113 // binary 2114 // certificate 2115 // certificate list 2116 // certificate pair 2117 // JPEG 2118 // octet string 2119 return "byte[]"; 2120 } 2121 else if (oid.equals("1.3.6.1.4.1.1466.115.121.1.24")) 2122 { 2123 // generalized time. 2124 needDate = true; 2125 return "Date"; 2126 } 2127 else if (oid.equals("1.3.6.1.4.1.1466.115.121.1.27")) 2128 { 2129 // integer 2130 return "Long"; 2131 } 2132 else if (oid.equals("1.3.6.1.4.1.1466.115.121.1.12") || 2133 oid.equals("1.3.6.1.4.1.1466.115.121.1.34")) 2134 { 2135 // DN 2136 // name and optional UID 2137 needDN = true; 2138 if (! d.isSingleValued()) 2139 { 2140 needPersistedObjects = true; 2141 } 2142 return "DN"; 2143 } 2144 else 2145 { 2146 return "String"; 2147 } 2148 } 2149 2150 2151 2152 /** 2153 * {@inheritDoc} 2154 */ 2155 @Override() 2156 public LinkedHashMap<String[],String> getExampleUsages() 2157 { 2158 final LinkedHashMap<String[],String> examples = 2159 new LinkedHashMap<>(StaticUtils.computeMapCapacity(1)); 2160 2161 final String[] args = 2162 { 2163 "--hostname", "server.example.com", 2164 "--port", "389", 2165 "--bindDN", "uid=admin,dc=example,dc=com", 2166 "--bindPassword", "password", 2167 "--outputDirectory", "src/com/example", 2168 "--structuralClass", "myStructuralClass", 2169 "--auxiliaryClass", "auxClass1", 2170 "--auxiliaryClass", "auxClass2", 2171 "--rdnAttribute", "cn", 2172 "--defaultParentDN", "dc=example,dc=com", 2173 "--packageName", "com.example", 2174 "--className", "MyObject" 2175 }; 2176 examples.put(args, INFO_GEN_SOURCE_EXAMPLE_1.get()); 2177 2178 return examples; 2179 } 2180}