649 lines
25 KiB
Java
649 lines
25 KiB
Java
package com.dmiki.metaplugin.xom;
|
|
|
|
import com.dmiki.metaplugin.xsd.model.XsdConfigItem;
|
|
import com.dmiki.metaplugin.xsd.model.XsdConfigMode;
|
|
|
|
import java.io.File;
|
|
import java.io.FileOutputStream;
|
|
import java.io.OutputStreamWriter;
|
|
import java.io.Writer;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.IdentityHashMap;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.LinkedHashSet;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
public class JavaEntityGenerator {
|
|
|
|
public File generate(XsdConfigItem root,
|
|
XomGenerateOptions options,
|
|
File outputDirectory) throws XomGenerationException {
|
|
if (root == null) {
|
|
throw new XomGenerationException("XOM-004", "实体生成失败: 根节点为空");
|
|
}
|
|
if (outputDirectory == null) {
|
|
throw new XomGenerationException("XOM-006", "实体生成失败: 输出目录为空");
|
|
}
|
|
if (!outputDirectory.exists() && !outputDirectory.mkdirs()) {
|
|
throw new XomGenerationException("XOM-006", "实体生成失败: 无法创建目录 " + outputDirectory.getAbsolutePath());
|
|
}
|
|
|
|
JavaTypeDescriptor rootType = parseRootType(options, root);
|
|
|
|
GenerationContext context = new GenerationContext();
|
|
String rootClassName = ensureUniqueClassName(rootType.className, context.classCounters);
|
|
|
|
List<ClassModel> classModels = new ArrayList<ClassModel>();
|
|
ClassModel rootModel = new ClassModel(rootClassName);
|
|
classModels.add(rootModel);
|
|
buildClassModel(root, rootModel, classModels, context);
|
|
|
|
List<File> targetFiles = new ArrayList<File>();
|
|
for (ClassModel model : classModels) {
|
|
File file = new File(outputDirectory, model.className + ".java");
|
|
if (file.exists() && !options.isOverwrite()) {
|
|
throw new XomGenerationException("XOM-006", "Java文件已存在且overwrite=false: " + file.getAbsolutePath());
|
|
}
|
|
targetFiles.add(file);
|
|
}
|
|
|
|
for (int i = 0; i < classModels.size(); i++) {
|
|
String source = renderSource(classModels.get(i), rootType.packageName);
|
|
writeSource(targetFiles.get(i), source);
|
|
}
|
|
return targetFiles.get(0);
|
|
}
|
|
|
|
private JavaTypeDescriptor parseRootType(XomGenerateOptions options, XsdConfigItem root) {
|
|
String fullType = trimToNull(options.getResultMapType());
|
|
if (fullType == null) {
|
|
return new JavaTypeDescriptor(null, toUpperCamel(safe(root.getXmlName())) + "Entity");
|
|
}
|
|
|
|
int idx = fullType.lastIndexOf('.');
|
|
if (idx < 0 || idx == fullType.length() - 1) {
|
|
return new JavaTypeDescriptor(null, sanitizeDeclaredClassName(fullType));
|
|
}
|
|
|
|
String packageName = fullType.substring(0, idx).trim();
|
|
String className = sanitizeDeclaredClassName(fullType.substring(idx + 1));
|
|
return new JavaTypeDescriptor(packageName.isEmpty() ? null : packageName, className);
|
|
}
|
|
|
|
private void buildClassModel(XsdConfigItem node,
|
|
ClassModel classModel,
|
|
List<ClassModel> allClasses,
|
|
GenerationContext context) {
|
|
Map<String, Integer> fieldCounters = new LinkedHashMap<String, Integer>();
|
|
appendSelfValueFieldIfNeeded(node, classModel, fieldCounters);
|
|
|
|
for (XsdConfigItem child : node.getChildren()) {
|
|
appendNodeAsField(classModel, child, fieldCounters, context, allClasses);
|
|
}
|
|
}
|
|
|
|
private void appendSelfValueFieldIfNeeded(XsdConfigItem node,
|
|
ClassModel classModel,
|
|
Map<String, Integer> fieldCounters) {
|
|
if (!shouldAppendSelfValueField(node)) {
|
|
return;
|
|
}
|
|
String fieldName = ensureUniqueField(resolveFieldName(node), fieldCounters);
|
|
String fieldType = resolveLeafType(node.getJavaType());
|
|
classModel.fields.add(new FieldModel(fieldName, fieldType));
|
|
}
|
|
|
|
private boolean shouldAppendSelfValueField(XsdConfigItem node) {
|
|
return isSimpleContentNode(node);
|
|
}
|
|
|
|
private void appendNodeAsField(ClassModel classModel,
|
|
XsdConfigItem item,
|
|
Map<String, Integer> fieldCounters,
|
|
GenerationContext context,
|
|
List<ClassModel> allClasses) {
|
|
boolean leaf = item.isEffectiveLeaf();
|
|
XsdConfigMode mode = effectiveMode(item, leaf);
|
|
if (leaf && mode == XsdConfigMode.IGNORE) {
|
|
return;
|
|
}
|
|
if (!leaf && mode == XsdConfigMode.FLATTEN_AND_IGNORE_CHILDREN) {
|
|
return;
|
|
}
|
|
if (!leaf && mode == XsdConfigMode.FLATTEN) {
|
|
for (XsdConfigItem child : item.getChildren()) {
|
|
appendNodeAsField(classModel, child, fieldCounters, context, allClasses);
|
|
}
|
|
return;
|
|
}
|
|
if (shouldInlineSimpleContentNode(item)) {
|
|
appendSimpleContentFieldsToParent(classModel, item, fieldCounters, context, allClasses);
|
|
return;
|
|
}
|
|
if (shouldInlineAttributeCarrierWrapperNode(item)) {
|
|
appendWrapperChildrenToParent(classModel, item, fieldCounters, context, allClasses);
|
|
return;
|
|
}
|
|
|
|
String fieldName = ensureUniqueField(resolveFieldName(item), fieldCounters);
|
|
boolean complexChild = !item.isEffectiveLeaf() && !item.isAttribute();
|
|
|
|
String baseType;
|
|
if (complexChild) {
|
|
String candidateClassName = sanitizeClassName(toUpperCamel(safe(item.getXmlName())));
|
|
String signature = buildClassSignature(item, context.signatureCache, new LinkedHashSet<XsdConfigItem>());
|
|
String shapeKey = buildShapeKey(candidateClassName, signature);
|
|
String reusedClassName = context.classNameByShapeKey.get(shapeKey);
|
|
if (reusedClassName != null) {
|
|
baseType = reusedClassName;
|
|
} else {
|
|
String nestedClassName = ensureUniqueClassName(candidateClassName, context.classCounters);
|
|
ClassModel nestedClass = new ClassModel(nestedClassName);
|
|
allClasses.add(nestedClass);
|
|
context.classNameByShapeKey.put(shapeKey, nestedClassName);
|
|
buildClassModel(item, nestedClass, allClasses, context);
|
|
baseType = nestedClassName;
|
|
}
|
|
} else {
|
|
baseType = resolveLeafType(item.getJavaType());
|
|
}
|
|
|
|
String fieldType = item.isRepeated() ? "List<" + baseType + ">" : baseType;
|
|
classModel.fields.add(new FieldModel(fieldName, fieldType));
|
|
}
|
|
|
|
private boolean shouldInlineSimpleContentNode(XsdConfigItem item) {
|
|
return isSimpleContentNode(item) && !item.isRepeated();
|
|
}
|
|
|
|
private boolean isSimpleContentNode(XsdConfigItem node) {
|
|
return node != null && !node.isAttribute() && node.hasOnlyAttributeChildren();
|
|
}
|
|
|
|
private void appendSimpleContentFieldsToParent(ClassModel classModel,
|
|
XsdConfigItem item,
|
|
Map<String, Integer> fieldCounters,
|
|
GenerationContext context,
|
|
List<ClassModel> allClasses) {
|
|
appendSelfValueFieldIfNeeded(item, classModel, fieldCounters);
|
|
for (XsdConfigItem child : item.getChildren()) {
|
|
appendNodeAsField(classModel, child, fieldCounters, context, allClasses);
|
|
}
|
|
}
|
|
|
|
private boolean shouldInlineAttributeCarrierWrapperNode(XsdConfigItem item) {
|
|
if (item == null || item.isRepeated() || item.isAttribute() || !item.hasChildren()) {
|
|
return false;
|
|
}
|
|
boolean hasAttributeCarrierChild = false;
|
|
for (XsdConfigItem child : item.getChildren()) {
|
|
if (!child.isEffectiveLeaf()) {
|
|
return false;
|
|
}
|
|
if (child.hasOnlyAttributeChildren()) {
|
|
hasAttributeCarrierChild = true;
|
|
}
|
|
}
|
|
return hasAttributeCarrierChild;
|
|
}
|
|
|
|
private void appendWrapperChildrenToParent(ClassModel classModel,
|
|
XsdConfigItem item,
|
|
Map<String, Integer> fieldCounters,
|
|
GenerationContext context,
|
|
List<ClassModel> allClasses) {
|
|
for (XsdConfigItem child : item.getChildren()) {
|
|
appendNodeAsField(classModel, child, fieldCounters, context, allClasses);
|
|
}
|
|
}
|
|
|
|
private String buildClassSignature(XsdConfigItem node,
|
|
Map<XsdConfigItem, String> signatureCache,
|
|
Set<XsdConfigItem> visiting) {
|
|
if (node == null) {
|
|
return "";
|
|
}
|
|
String cached = signatureCache.get(node);
|
|
if (cached != null) {
|
|
return cached;
|
|
}
|
|
if (visiting.contains(node)) {
|
|
return "RECURSIVE(" + sanitizeClassName(toUpperCamel(safe(node.getXmlName()))) + ")";
|
|
}
|
|
visiting.add(node);
|
|
|
|
Map<String, Integer> fieldCounters = new LinkedHashMap<String, Integer>();
|
|
List<String> entries = new ArrayList<String>();
|
|
appendSelfValueSignatureIfNeeded(node, fieldCounters, entries);
|
|
for (XsdConfigItem child : node.getChildren()) {
|
|
appendNodeSignatureEntries(child, fieldCounters, entries, signatureCache, visiting);
|
|
}
|
|
|
|
visiting.remove(node);
|
|
String signature = String.join("|", entries);
|
|
signatureCache.put(node, signature);
|
|
return signature;
|
|
}
|
|
|
|
private void appendSelfValueSignatureIfNeeded(XsdConfigItem node,
|
|
Map<String, Integer> fieldCounters,
|
|
List<String> entries) {
|
|
if (!shouldAppendSelfValueField(node)) {
|
|
return;
|
|
}
|
|
String fieldName = ensureUniqueField(resolveFieldName(node), fieldCounters);
|
|
String fieldType = resolveLeafType(node.getJavaType());
|
|
entries.add(fieldName + ":" + fieldType);
|
|
}
|
|
|
|
private void appendNodeSignatureEntries(XsdConfigItem item,
|
|
Map<String, Integer> fieldCounters,
|
|
List<String> entries,
|
|
Map<XsdConfigItem, String> signatureCache,
|
|
Set<XsdConfigItem> visiting) {
|
|
boolean leaf = item.isEffectiveLeaf();
|
|
XsdConfigMode mode = effectiveMode(item, leaf);
|
|
if (leaf && mode == XsdConfigMode.IGNORE) {
|
|
return;
|
|
}
|
|
if (!leaf && mode == XsdConfigMode.FLATTEN_AND_IGNORE_CHILDREN) {
|
|
return;
|
|
}
|
|
if (!leaf && mode == XsdConfigMode.FLATTEN) {
|
|
for (XsdConfigItem child : item.getChildren()) {
|
|
appendNodeSignatureEntries(child, fieldCounters, entries, signatureCache, visiting);
|
|
}
|
|
return;
|
|
}
|
|
if (shouldInlineSimpleContentNode(item)) {
|
|
appendSelfValueSignatureIfNeeded(item, fieldCounters, entries);
|
|
for (XsdConfigItem child : item.getChildren()) {
|
|
appendNodeSignatureEntries(child, fieldCounters, entries, signatureCache, visiting);
|
|
}
|
|
return;
|
|
}
|
|
if (shouldInlineAttributeCarrierWrapperNode(item)) {
|
|
for (XsdConfigItem child : item.getChildren()) {
|
|
appendNodeSignatureEntries(child, fieldCounters, entries, signatureCache, visiting);
|
|
}
|
|
return;
|
|
}
|
|
|
|
String fieldName = ensureUniqueField(resolveFieldName(item), fieldCounters);
|
|
boolean complexChild = !item.isEffectiveLeaf() && !item.isAttribute();
|
|
String baseType;
|
|
if (complexChild) {
|
|
String childBaseName = sanitizeClassName(toUpperCamel(safe(item.getXmlName())));
|
|
String childSignature = buildClassSignature(item, signatureCache, visiting);
|
|
baseType = "{" + childBaseName + "#" + childSignature + "}";
|
|
} else {
|
|
baseType = resolveLeafType(item.getJavaType());
|
|
}
|
|
String fieldType = item.isRepeated() ? "List<" + baseType + ">" : baseType;
|
|
entries.add(fieldName + ":" + fieldType);
|
|
}
|
|
|
|
private String buildShapeKey(String className, String signature) {
|
|
return className.toLowerCase(Locale.ROOT) + "|" + signature;
|
|
}
|
|
|
|
private XsdConfigMode effectiveMode(XsdConfigItem item, boolean leaf) {
|
|
XsdConfigMode mode = item.getConfigMode();
|
|
if (leaf) {
|
|
return mode == XsdConfigMode.IGNORE ? XsdConfigMode.IGNORE : XsdConfigMode.KEEP;
|
|
}
|
|
if (mode == XsdConfigMode.PRESERVE_HIERARCHY_AND_ATTRIBUTES
|
|
|| mode == XsdConfigMode.PRESERVE_HIERARCHY
|
|
|| mode == XsdConfigMode.FLATTEN
|
|
|| mode == XsdConfigMode.FLATTEN_AND_IGNORE_CHILDREN) {
|
|
return mode;
|
|
}
|
|
if (mode == XsdConfigMode.IGNORE) {
|
|
return XsdConfigMode.FLATTEN_AND_IGNORE_CHILDREN;
|
|
}
|
|
return XsdConfigMode.PRESERVE_HIERARCHY_AND_ATTRIBUTES;
|
|
}
|
|
|
|
private String renderSource(ClassModel rootModel, String packageName) {
|
|
StringBuilder builder = new StringBuilder(2048);
|
|
Set<String> imports = new LinkedHashSet<String>();
|
|
collectImports(rootModel, imports);
|
|
|
|
if (packageName != null) {
|
|
builder.append("package ").append(packageName).append(";\n\n");
|
|
}
|
|
|
|
for (String anImport : imports) {
|
|
builder.append("import ").append(anImport).append(";\n");
|
|
}
|
|
if (!imports.isEmpty()) {
|
|
builder.append("\n");
|
|
}
|
|
|
|
builder.append("public class ").append(rootModel.className).append(" {\n\n");
|
|
renderFieldsAndAccessors(builder, rootModel, 1);
|
|
builder.append("}\n");
|
|
return builder.toString();
|
|
}
|
|
|
|
private void renderFieldsAndAccessors(StringBuilder builder, ClassModel classModel, int indentLevel) {
|
|
for (FieldModel field : classModel.fields) {
|
|
indent(builder, indentLevel);
|
|
builder.append("private ").append(field.type).append(" ").append(field.name).append(";\n");
|
|
}
|
|
if (!classModel.fields.isEmpty()) {
|
|
builder.append("\n");
|
|
}
|
|
for (FieldModel field : classModel.fields) {
|
|
String getterName = "get" + toUpperCamel(field.name);
|
|
String setterName = "set" + toUpperCamel(field.name);
|
|
|
|
indent(builder, indentLevel);
|
|
builder.append("public ").append(field.type).append(" ").append(getterName).append("() {\n");
|
|
indent(builder, indentLevel + 1);
|
|
builder.append("return ").append(field.name).append(";\n");
|
|
indent(builder, indentLevel);
|
|
builder.append("}\n\n");
|
|
|
|
indent(builder, indentLevel);
|
|
builder.append("public void ").append(setterName).append("(").append(field.type).append(" ").append(field.name).append(") {\n");
|
|
indent(builder, indentLevel + 1);
|
|
builder.append("this.").append(field.name).append(" = ").append(field.name).append(";\n");
|
|
indent(builder, indentLevel);
|
|
builder.append("}\n\n");
|
|
}
|
|
}
|
|
|
|
private void collectImports(ClassModel classModel, Set<String> imports) {
|
|
for (FieldModel field : classModel.fields) {
|
|
String type = field.type;
|
|
if (type.startsWith("List<")) {
|
|
imports.add("java.util.List");
|
|
String inner = type.substring("List<".length(), type.length() - 1);
|
|
addTypeImport(inner, imports);
|
|
} else {
|
|
addTypeImport(type, imports);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void writeSource(File javaFile, String source) throws XomGenerationException {
|
|
try (Writer writer = new OutputStreamWriter(new FileOutputStream(javaFile), StandardCharsets.UTF_8)) {
|
|
writer.write(source);
|
|
writer.flush();
|
|
} catch (Exception ex) {
|
|
throw new XomGenerationException("XOM-006", "写入Java实体失败: " + ex.getMessage());
|
|
}
|
|
}
|
|
|
|
private void addTypeImport(String type, Set<String> imports) {
|
|
if (type == null) {
|
|
return;
|
|
}
|
|
if ("BigDecimal".equals(type)) {
|
|
imports.add("java.math.BigDecimal");
|
|
return;
|
|
}
|
|
if ("LocalDate".equals(type)) {
|
|
imports.add("java.time.LocalDate");
|
|
return;
|
|
}
|
|
if ("LocalDateTime".equals(type)) {
|
|
imports.add("java.time.LocalDateTime");
|
|
return;
|
|
}
|
|
if ("LocalTime".equals(type)) {
|
|
imports.add("java.time.LocalTime");
|
|
return;
|
|
}
|
|
if (type.contains(".") && !type.startsWith("java.lang.")) {
|
|
imports.add(type);
|
|
}
|
|
}
|
|
|
|
private String resolveFieldName(XsdConfigItem item) {
|
|
String candidate = trimToNull(item.getJavaProperty());
|
|
if (candidate == null) {
|
|
candidate = toLowerCamel(safe(item.getXmlName()));
|
|
}
|
|
return sanitizeFieldName(candidate);
|
|
}
|
|
|
|
private String resolveLeafType(String configuredType) {
|
|
String type = trimToNull(configuredType);
|
|
if (type == null) {
|
|
return "String";
|
|
}
|
|
if ("byte[]".equals(type)) {
|
|
return "byte[]";
|
|
}
|
|
if (type.contains(".")) {
|
|
return type;
|
|
}
|
|
return sanitizeClassName(type);
|
|
}
|
|
|
|
private String ensureUniqueField(String name, Map<String, Integer> counters) {
|
|
String key = name.toLowerCase(Locale.ROOT);
|
|
Integer counter = counters.get(key);
|
|
if (counter == null) {
|
|
counters.put(key, 1);
|
|
return name;
|
|
}
|
|
int next = counter + 1;
|
|
counters.put(key, next);
|
|
return name + next;
|
|
}
|
|
|
|
private String ensureUniqueClassName(String className, Map<String, Integer> counters) {
|
|
String key = className.toLowerCase(Locale.ROOT);
|
|
Integer counter = counters.get(key);
|
|
if (counter == null) {
|
|
counters.put(key, 1);
|
|
return className;
|
|
}
|
|
int next = counter + 1;
|
|
counters.put(key, next);
|
|
return className + next;
|
|
}
|
|
|
|
private String sanitizeClassName(String text) {
|
|
String value = trimToNull(text);
|
|
if (value == null) {
|
|
return "GeneratedEntity";
|
|
}
|
|
String className = toUpperCamel(value);
|
|
if (className.isEmpty()) {
|
|
className = "GeneratedEntity";
|
|
}
|
|
if (!Character.isJavaIdentifierStart(className.charAt(0))) {
|
|
className = "C" + className;
|
|
}
|
|
return stripInvalidIdentifierChars(className);
|
|
}
|
|
|
|
private String sanitizeDeclaredClassName(String text) {
|
|
String value = trimToNull(text);
|
|
if (value == null) {
|
|
return "GeneratedEntity";
|
|
}
|
|
String className = value
|
|
.replaceAll("[^A-Za-z0-9_]+", "_")
|
|
.replaceAll("_+", "_")
|
|
.replaceAll("^_+|_+$", "");
|
|
if (className.isEmpty()) {
|
|
return "GeneratedEntity";
|
|
}
|
|
if (!Character.isJavaIdentifierStart(className.charAt(0))) {
|
|
className = "C_" + className;
|
|
}
|
|
className = stripInvalidIdentifierChars(className);
|
|
if (className.isEmpty() || "_".equals(className)) {
|
|
return "GeneratedEntity";
|
|
}
|
|
if (JAVA_KEYWORDS.contains(className.toLowerCase(Locale.ROOT))) {
|
|
className = className + "Type";
|
|
}
|
|
return className;
|
|
}
|
|
|
|
private String sanitizeFieldName(String text) {
|
|
String value = trimToNull(text);
|
|
if (value == null) {
|
|
return "field";
|
|
}
|
|
String fieldName = toLowerCamel(value);
|
|
if (fieldName.isEmpty()) {
|
|
fieldName = "field";
|
|
}
|
|
if (!Character.isJavaIdentifierStart(fieldName.charAt(0))) {
|
|
fieldName = "_" + fieldName;
|
|
}
|
|
fieldName = stripInvalidIdentifierChars(fieldName);
|
|
if (JAVA_KEYWORDS.contains(fieldName)) {
|
|
fieldName = fieldName + "Field";
|
|
}
|
|
return fieldName;
|
|
}
|
|
|
|
private String stripInvalidIdentifierChars(String text) {
|
|
StringBuilder builder = new StringBuilder();
|
|
for (int i = 0; i < text.length(); i++) {
|
|
char current = text.charAt(i);
|
|
if (i == 0) {
|
|
if (Character.isJavaIdentifierStart(current)) {
|
|
builder.append(current);
|
|
}
|
|
continue;
|
|
}
|
|
if (Character.isJavaIdentifierPart(current)) {
|
|
builder.append(current);
|
|
}
|
|
}
|
|
return builder.toString();
|
|
}
|
|
|
|
private void indent(StringBuilder builder, int indentLevel) {
|
|
for (int i = 0; i < indentLevel * 4; i++) {
|
|
builder.append(' ');
|
|
}
|
|
}
|
|
|
|
private String safe(String text) {
|
|
return text == null ? "" : text;
|
|
}
|
|
|
|
private String trimToNull(String text) {
|
|
if (text == null) {
|
|
return null;
|
|
}
|
|
String trimmed = text.trim();
|
|
if (trimmed.isEmpty()) {
|
|
return null;
|
|
}
|
|
return trimmed;
|
|
}
|
|
|
|
private String toUpperCamel(String source) {
|
|
if (source == null || source.trim().isEmpty()) {
|
|
return "";
|
|
}
|
|
String cleaned = source.replaceAll("[^A-Za-z0-9]+", " ").trim();
|
|
if (cleaned.isEmpty()) {
|
|
return "";
|
|
}
|
|
String[] parts = cleaned.split("\\s+");
|
|
StringBuilder builder = new StringBuilder();
|
|
for (String part : parts) {
|
|
if (part.isEmpty()) {
|
|
continue;
|
|
}
|
|
if (part.length() == 1) {
|
|
builder.append(part.toUpperCase(Locale.ROOT));
|
|
} else {
|
|
builder.append(part.substring(0, 1).toUpperCase(Locale.ROOT));
|
|
builder.append(part.substring(1));
|
|
}
|
|
}
|
|
return builder.toString();
|
|
}
|
|
|
|
private String toLowerCamel(String source) {
|
|
String upper = toUpperCamel(source);
|
|
if (upper.isEmpty()) {
|
|
return "";
|
|
}
|
|
if (isAllUpperCaseLetters(upper)) {
|
|
return upper.toLowerCase(Locale.ROOT);
|
|
}
|
|
if (upper.length() == 1) {
|
|
return upper.toLowerCase(Locale.ROOT);
|
|
}
|
|
return upper.substring(0, 1).toLowerCase(Locale.ROOT) + upper.substring(1);
|
|
}
|
|
|
|
private boolean isAllUpperCaseLetters(String text) {
|
|
boolean hasLetter = false;
|
|
for (int i = 0; i < text.length(); i++) {
|
|
char current = text.charAt(i);
|
|
if (!Character.isLetter(current)) {
|
|
continue;
|
|
}
|
|
hasLetter = true;
|
|
if (!Character.isUpperCase(current)) {
|
|
return false;
|
|
}
|
|
}
|
|
return hasLetter;
|
|
}
|
|
|
|
private static class JavaTypeDescriptor {
|
|
private final String packageName;
|
|
private final String className;
|
|
|
|
private JavaTypeDescriptor(String packageName, String className) {
|
|
this.packageName = packageName;
|
|
this.className = className;
|
|
}
|
|
}
|
|
|
|
private static class ClassModel {
|
|
private final String className;
|
|
private final List<FieldModel> fields = new ArrayList<FieldModel>();
|
|
|
|
private ClassModel(String className) {
|
|
this.className = className;
|
|
}
|
|
}
|
|
|
|
private static class GenerationContext {
|
|
private final Map<String, Integer> classCounters = new LinkedHashMap<String, Integer>();
|
|
private final Map<String, String> classNameByShapeKey = new LinkedHashMap<String, String>();
|
|
private final Map<XsdConfigItem, String> signatureCache = new IdentityHashMap<XsdConfigItem, String>();
|
|
}
|
|
|
|
private static class FieldModel {
|
|
private final String name;
|
|
private final String type;
|
|
|
|
private FieldModel(String name, String type) {
|
|
this.name = name;
|
|
this.type = type;
|
|
}
|
|
}
|
|
|
|
private static final Set<String> JAVA_KEYWORDS = new LinkedHashSet<String>(Arrays.asList(
|
|
"abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class",
|
|
"const", "continue", "default", "do", "double", "else", "enum", "extends", "final",
|
|
"finally", "float", "for", "goto", "if", "implements", "import", "instanceof",
|
|
"int", "interface", "long", "native", "new", "package", "private", "protected",
|
|
"public", "return", "short", "static", "strictfp", "super", "switch", "synchronized",
|
|
"this", "throw", "throws", "transient", "try", "void", "volatile", "while"
|
|
));
|
|
}
|