/******************************************************************************* * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation from Oracle TopLink ******************************************************************************/ package org.eclipse.persistence.internal.codegen; import java.util.*; /** * INTERNAL: * <p><b>Purpose</b>: Model a element of code generation purposes. * * @since TopLink 3.0 * @author James Sutherland */ public abstract class CodeDefinition { protected AccessLevel accessLevel; protected String name; protected String comment; protected static final String JAVA_LANG_PACKAGE_NAME = "java.lang"; protected static final String JAVA_UTIL_PACKAGE_NAME = "java.util"; protected static final String TOPLINK_INDIRECTION_PACKAGE_NAME = "org.eclipse.persistence.indirection"; public CodeDefinition() { this.accessLevel = new AccessLevel(); this.name = ""; this.comment = ""; } private static boolean adjustmentNeededForType(String typeName, Map typeNameMap) { if ((typeName == null) || typeName.equals("")) { return false; } if (packageName(typeName).length() == 0) { return false; } Set packages = (Set)typeNameMap.get(shortName(typeName)); return (packages == null) || (packages.size() <= 1); } /** * Compares the typeName to those stored in the typeNameMap. * If the short name of the typeName is unambiguous (only one package for * that short name in the Map), removes the package name and returns the * short name, else returns the whole thing. * * Assumes that typeName contains only a package name (optional) and a short name, * potentially with subtended brackets. * * (e.g. int -> int, java.util.Vector -> Vector, java.lang.Boolean[] -> Boolean[], etc.) */ protected static String adjustTypeName(String typeName, Map typeNameMap) { if (adjustmentNeededForType(typeName, typeNameMap)) { putTypeNameInMap(typeName, typeNameMap); return typeName.substring(packageName(typeName).length() + 1); } else { return typeName; } } /** * Returns a set of java.lang.String type names included in longString. * Will only look for ValueHolder, java.util collection types, and TopLink * indirect collection types. * All other searches too intractable at this point. */ protected static Set parseForTypeNames(String longString) { Set typeNames = new HashSet(); if (longString != null) { typeNames.addAll(parseForTypeNamesInPackage(longString, JAVA_LANG_PACKAGE_NAME)); typeNames.addAll(parseForTypeNamesInPackage(longString, JAVA_UTIL_PACKAGE_NAME)); typeNames.addAll(parseForTypeNamesInPackage(longString, TOPLINK_INDIRECTION_PACKAGE_NAME)); } return typeNames; } private static Set parseForTypeNamesInPackage(String longString, String packageName) { Set typeNames = new HashSet(); int packageStartIndex = longString.indexOf(packageName); while (packageStartIndex != -1) { boolean lookingForEndOfTypeName = true; int searchIndex = packageStartIndex + packageName.length() + 1; while (lookingForEndOfTypeName) { if (Character.isJavaIdentifierPart(longString.charAt(searchIndex))) { searchIndex++; } else { lookingForEndOfTypeName = false; } } typeNames.add(longString.substring(packageStartIndex, searchIndex)); packageStartIndex = longString.indexOf(packageName, searchIndex); } return typeNames; } /** * Used for calculating imports. @see org.eclipse.persistence.internal.codegen.ClassDefinition#calculateImports() */ protected static void putTypeNameInMap(String typeName, Map typeNameMap) { if ((typeName == null) || typeName.equals("")) { return; } String shortName = shortName(typeName); String packageName = packageName(typeName); if (packageName.length() > 0) { Set packageNames; if (typeNameMap.get(shortName) == null) { packageNames = new HashSet(); typeNameMap.put(shortName, packageNames); } else { packageNames = (Set)typeNameMap.get(shortName); } // There is no package name. The package is the default package. // Do nothing, as neither an import is needed, nor does the class need to be unqualified. if (!packageNames.contains(packageName)) { packageNames.add(packageName); } } } private static String packageName(String typeName) { int lastPeriod = typeName.lastIndexOf("."); if (lastPeriod == -1) { return ""; } else { return typeName.substring(0, lastPeriod); } } /** * Removes the package name, if there is one. Also removes any trailing brackets. * * Assumes that typeName contains only a package name (optional) and a short name, * potentially with subtended brackets. * * (e.g. int -> int, java.util.Vector -> Vector, java.lang.Boolean[] -> Boolean, etc.) */ private static String shortName(String typeName) { int shortNameStartIndex = typeName.lastIndexOf(".") + 1; int searchIndex = shortNameStartIndex; boolean stillLookingForEnd = true; while (stillLookingForEnd) { if (Character.isJavaIdentifierPart(typeName.charAt(searchIndex))) { searchIndex++; stillLookingForEnd = searchIndex < typeName.length(); } else { stillLookingForEnd = false; } } return typeName.substring(shortNameStartIndex, searchIndex); } public AccessLevel getAccessLevel() { return accessLevel; } public String getComment() { return comment; } public String getName() { return name; } public void setAccessLevel(AccessLevel accessLevel) { this.accessLevel = accessLevel; } public void setComment(String comment) { this.comment = comment; } public void setName(String name) { this.name = name; } public String toString() { CodeGenerator generator = new CodeGenerator(); write(generator); return generator.toString(); } /** * Write the code out to the generator's stream. */ public void write(CodeGenerator generator) { if (getComment().length() > 0) { generator.writeln("/**"); String comment = getComment(); String cr = org.eclipse.persistence.internal.helper.Helper.cr(); int lastLineIndex = 0; int nextLineIndex = comment.indexOf(cr); while (nextLineIndex != -1) { generator.write(" * "); generator.write(comment.substring(lastLineIndex, nextLineIndex + cr.length())); lastLineIndex = nextLineIndex + cr.length(); nextLineIndex = comment.indexOf(cr, lastLineIndex); } generator.write(" * "); generator.writeln(comment.substring(lastLineIndex, comment.length())); generator.writeln(" */"); generator.cr(); } getAccessLevel().write(generator); generator.write(" "); writeBody(generator); } /** * Write the code out to the generator's stream. */ public abstract void writeBody(CodeGenerator generator); }