From 23441310e06a2ec025c59db5ee02475f119b8048 Mon Sep 17 00:00:00 2001 From: Peter Date: Sun, 17 Dec 2023 10:25:14 -0500 Subject: [PATCH 01/16] Initial commit of the Compiler class --- src/javaxt/orm/Compiler.java | 272 +++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 src/javaxt/orm/Compiler.java diff --git a/src/javaxt/orm/Compiler.java b/src/javaxt/orm/Compiler.java new file mode 100644 index 0000000..d38ec8b --- /dev/null +++ b/src/javaxt/orm/Compiler.java @@ -0,0 +1,272 @@ +package javaxt.orm; + +import java.io.*; +import java.net.*; +import java.util.*; +import javax.tools.*; +import java.nio.charset.Charset; + +import static javaxt.utils.Console.console; + +//****************************************************************************** +//** Compiler +//****************************************************************************** +/** + * Used to compile ORM models into Java classes. The classes are ephemeral + * meaning they are not saved anywhere on disk (no class files or jar files). + * Instead the classes are stored in memory and are tied to the lifecycle of + * the JVM. + * + ******************************************************************************/ + +public class Compiler { + + private Class[] classes; + private HashMap outputFiles; + private URLClassLoader urlClassLoader; + private DiagnosticListener listener = null; + private Locale locale = null; + private Charset charset = Charset.defaultCharset(); + + + //************************************************************************** + //** Constructor + //************************************************************************** + public Compiler(Model[] models) throws Exception { + + if (models==null || models.length==0){ + classes = new Class[0]; + } + else{ + + outputFiles = new HashMap<>(); + urlClassLoader = getClassLoader(); + + + + //Convert models into an ArrayList + ArrayList arr = new ArrayList<>(); + for (Model model : models){ + arr.add(model); + } + + + //Compile classes + ArrayList classes = new ArrayList<>(); + int numErrors = 0; + while (classes.size()(models.length*models.length)){ + throw new Exception("Failed to compile " + getClassName(arr.get(0))); + } + } + + + //Convert the class list into an array. Sorts the classes to match + //the order of the input models. + this.classes = new Class[classes.size()]; + for (int i=0; i arr = new ArrayList<>(); + Iterator it = outputFiles.keySet().iterator(); + while (it.hasNext()){ + String name = it.next(); + if (name.startsWith(packageName + ".")){ + if (!name.equals(className)){ //don't include the current file since it hasn't been compiled yet + arr.add(outputFiles.get(name)); + } + } + } + if (!arr.isEmpty()) return arr; + } + + return super.list(location, packageName, kinds, recurse); + } + + + + public String inferBinaryName(JavaFileManager.Location location, JavaFileObject file) { + + if (location==StandardLocation.CLASS_PATH){ + Iterator it = outputFiles.keySet().iterator(); + while (it.hasNext()){ + String name = it.next(); + SimpleJavaFileObject f = outputFiles.get(name); + if (file==f) return name; + } + } + + return super.inferBinaryName(location, file); + } + }; + + + + + //Compile class + JavaCompiler.CompilationTask task = c.getTask( + null, + fileManager, + listener, + Collections.emptySet(), + Collections.emptySet(), + Collections.singleton(src) + ); + + if (task.call()) { + return urlClassLoader.loadClass(className); + } + else{ + throw new Exception("Failed to compile " + className); + } + } + + + //************************************************************************** + //** getClassLoader + //************************************************************************** + /** Returns a custom class loader used to find classes created by this class + */ + private URLClassLoader getClassLoader(){ + return new URLClassLoader(new URL[0]){ + protected Class findClass(final String name) throws ClassNotFoundException { + + + SimpleJavaFileObject f = outputFiles.get(name); + if (f!=null){ + try (InputStream is = f.openInputStream()) { + + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + int x; + byte[] buffer = new byte[256]; + while ((x = is.read(buffer, 0, buffer.length)) != -1) { + out.write(buffer, 0, x); + } + + out.flush(); + byte[] classBytes = out.toByteArray(); + return defineClass(name, classBytes, 0, classBytes.length); + + } + catch(Exception e){ + e.printStackTrace(); + } + } + + return super.findClass(name); + } + }; + } + + + //************************************************************************** + //** getClassName + //************************************************************************** + private String getClassName(Model model){ + return model.getPackageName() + "." + model.getName(); + } + + +} \ No newline at end of file From e856e793df5ba053648a136a0548750b91e15cc3 Mon Sep 17 00:00:00 2001 From: Peter Date: Sun, 17 Dec 2023 10:33:03 -0500 Subject: [PATCH 02/16] Tweaked validation logic in Main --- src/javaxt/orm/Main.java | 130 ++++++++++++++++++++++----------------- 1 file changed, 72 insertions(+), 58 deletions(-) diff --git a/src/javaxt/orm/Main.java b/src/javaxt/orm/Main.java index 4c905c0..73739e1 100644 --- a/src/javaxt/orm/Main.java +++ b/src/javaxt/orm/Main.java @@ -1,59 +1,73 @@ -package javaxt.orm; -import java.util.*; -import javaxt.io.Jar; -import static javaxt.utils.Console.console; - -//****************************************************************************** -//** Main -//****************************************************************************** -/** - * Command line interface used to parse a model file and generate Java and SQL - * output files. - * - ******************************************************************************/ - -public class Main { - - - //************************************************************************** - //** main - //************************************************************************** - /** Entry point for the application - * @param arguments Command line arguments - */ - public static void main(String[] arguments) throws Exception { - HashMap args = console.parseArgs(arguments); - - - //Print version as needed - if (args.containsKey("-version")){ - Jar jar = new Jar(Main.class); - javaxt.io.File jarFile = new javaxt.io.File(jar.getFile()); - String version = jar.getVersion(); - if (version==null) version = "Unknown"; - System.out.println(jarFile.getName(false) + " version \"" + version + "\""); - return; - } - - - //Parse inputs - String input = args.get("-input"); - String output = args.get("-output"); - if (input==null){ - input = arguments[0]; - if (arguments.length>1) output = arguments[1]; - } - javaxt.io.File inputFile = new javaxt.io.File(input); - if (!inputFile.exists()) throw new IllegalArgumentException("Input file not found"); - javaxt.io.Directory outputDirectory = output==null ? - inputFile.getDirectory() : new javaxt.io.Directory(output); - - - //Create models - Model[] models = new Parser(inputFile.getText()).getModels(); - - - //Create files - Writer.write(models, outputDirectory); - } +package javaxt.orm; +import java.util.*; +import javaxt.io.Jar; +import static javaxt.utils.Console.console; + +//****************************************************************************** +//** Main +//****************************************************************************** +/** + * Command line interface used to parse a model file and generate Java and SQL + * output files. + * + ******************************************************************************/ + +public class Main { + + + //************************************************************************** + //** main + //************************************************************************** + /** Entry point for the application + * @param arguments Command line arguments + */ + public static void main(String[] arguments) throws Exception { + HashMap args = console.parseArgs(arguments); + + + //Print version as needed + if (args.containsKey("-version")){ + Jar jar = new Jar(Main.class); + javaxt.io.File jarFile = new javaxt.io.File(jar.getFile()); + String version = jar.getVersion(); + if (version==null) version = "Unknown"; + System.out.println(jarFile.getName(false) + " version \"" + version + "\""); + return; + } + + + //Parse inputs + String input = args.get("-input"); + String output = args.get("-output"); + if (input==null){ + if (arguments.length>0) input = arguments[0]; + if (arguments.length>1) output = arguments[1]; + } + + + //Get input file + javaxt.io.File inputFile; + try{ + if (input==null) throw new IllegalArgumentException("Input file is required"); + inputFile = new javaxt.io.File(input); + if (!inputFile.exists()) throw new IllegalArgumentException("Input file not found"); + } + catch(Exception e){ + System.out.println(e.getMessage()); + return; + } + + + //Get output directory + javaxt.io.Directory outputDirectory = output==null ? + inputFile.getDirectory() : new javaxt.io.Directory(output); + + + //Create models + Model[] models = new Parser(inputFile.getText()).getModels(); + + + //Create files + Writer.write(models, outputDirectory); + } } \ No newline at end of file From a4b6fe8141349a23abdd3e58b9191bce54f08cf9 Mon Sep 17 00:00:00 2001 From: pborissow Date: Tue, 19 Dec 2023 12:13:37 -0500 Subject: [PATCH 03/16] Added support for inline field constraints and default values in the Model parser --- src/javaxt/orm/Model.java | 124 +++++++++++++++++++++++--------------- 1 file changed, 77 insertions(+), 47 deletions(-) diff --git a/src/javaxt/orm/Model.java b/src/javaxt/orm/Model.java index fee6fd8..ed9eb8a 100644 --- a/src/javaxt/orm/Model.java +++ b/src/javaxt/orm/Model.java @@ -61,17 +61,19 @@ protected Model(String modelName, JSONObject modelInfo, String packageName, Hash //Parse fields JSONArray arr = modelInfo.get("fields").toJSONArray(); - if (arr!=null) - for (int i=0; i Date: Tue, 19 Dec 2023 12:19:18 -0500 Subject: [PATCH 04/16] Initial commit of onTagCreateRelease.yml --- .github/workflows/onTagCreateRelease.yml | 79 ++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 .github/workflows/onTagCreateRelease.yml diff --git a/.github/workflows/onTagCreateRelease.yml b/.github/workflows/onTagCreateRelease.yml new file mode 100644 index 0000000..50df544 --- /dev/null +++ b/.github/workflows/onTagCreateRelease.yml @@ -0,0 +1,79 @@ +name: Create Release + +on: + push: + tags: + - "v*" # Push events to matching v*, i.e. v1.0, v20.15.10 + + +jobs: + build: + name: Create Release + runs-on: ubuntu-latest + steps: + + - name: Checkout code + uses: actions/checkout@v2 + + + - name: Create release name using the tag name + run: | + githubRef=${{ github.ref }} + githubRef="${githubRef/'refs/tags'/''}" + githubRef="${githubRef/'/'/''}" + githubRef="${githubRef/'v'/''}" + echo "releaseLabel=$githubRef" >> $GITHUB_ENV + + + - name: Print release label + run: echo $releaseLabel + + + - name: Create release directory + run: mkdir -p release/bin + + + ### Generate jar file + + - name: Set up JDK 11 + uses: actions/setup-java@v2 + with: + java-version: '11' + distribution: 'adopt' + + + - name: Install Maven + run: sudo apt install maven + + + - name: Check Maven Version + run: mvn -version + + + - name: Build jar using Maven + run: mvn --batch-mode install verify -U -X + + + ### Create zip file + + - name: Copy jar file from the dist to the release directory + run: cp dist/javaxt-orm*.jar release/bin/javaxt-orm.jar + + + - name: Copy release assets to the release directory + run: cp -r src LICENSE.TXT release + + + - name: Create zip file + run: cd release; zip -r ../javaxt-orm_v${{ env.releaseLabel }}.zip * + + + ### Upload zip file to javaxt.com + + - name: Upload release to server + run: >- + curl -X POST -L + -H "Authorization: ${{ secrets.UPLOAD_AUTH }}" + -F "file=@javaxt-orm_v${{ env.releaseLabel }}.zip;type=application/zip" + "${{ secrets.UPLOAD_URL }}" + From 6123f40000dc9e3db50c9f5c333f191306fbfbe7 Mon Sep 17 00:00:00 2001 From: Peter Date: Tue, 19 Dec 2023 12:27:53 -0500 Subject: [PATCH 05/16] Updated gitignore --- .gitignore | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 5a73ffd..ef80201 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ -build/ -dist/ -nbproject/ -build.xml -manifest.mf \ No newline at end of file +/build/ +/dist/ +/target/ +/nbproject/ +/build.xml +/manifest.mf + From 8794f92ddae7ba816e66486bd0e463f7f2aa7e7a Mon Sep 17 00:00:00 2001 From: pborissow Date: Wed, 20 Dec 2023 12:04:01 -0500 Subject: [PATCH 06/16] Fixing pom.xml --- pom.xml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 352a3d5..521ad3c 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ javaxt javaxt-core - 2.0.0 + 2.1.5 org.openjdk.nashorn @@ -52,6 +52,20 @@ ${src.dir} + + + + false + src + + **/*.java + + + + + + + From 64b95eaf92cb4d509527937d20fc9769e022540a Mon Sep 17 00:00:00 2001 From: pborissow Date: Tue, 26 Mar 2024 13:53:29 -0400 Subject: [PATCH 07/16] Added support for String[] and Integer[] arrays in the Field class --- src/javaxt/orm/Field.java | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/javaxt/orm/Field.java b/src/javaxt/orm/Field.java index d73f21b..131fac0 100644 --- a/src/javaxt/orm/Field.java +++ b/src/javaxt/orm/Field.java @@ -30,8 +30,14 @@ protected Field(String name, String type){ this.name = name; this.columnName = Utils.camelCaseToUnderScore(name); + //Set columnType and tweak type as needed if (type.equalsIgnoreCase("int")){ - type = "integer"; + type = "Integer"; + columnType = "integer"; + } + else if (type.equalsIgnoreCase("int[]")){ + type = "Integer[]"; + columnType = "integer array"; } else if (type.equalsIgnoreCase("long")){ columnType = "bigint"; @@ -44,9 +50,13 @@ else if (type.equalsIgnoreCase("decimal") || type.equalsIgnoreCase("numeric")){ type = "BigDecimal"; columnType = "numeric"; } - else if (type.equalsIgnoreCase("text") || type.equalsIgnoreCase("string")){ - type = "string"; - columnType = "text"; + else if (type.equalsIgnoreCase("text") || type.equalsIgnoreCase("string") || type.equalsIgnoreCase("password")){ + type = "String"; + columnType = "varchar"; //varchar without the length specifier and text are equivalent + } + else if (type.equalsIgnoreCase("text[]") || type.equalsIgnoreCase("string[]")){ + type = "String[]"; + columnType = "varchar array"; //same as "text array" } else if (type.equalsIgnoreCase("char")){ type = "string"; @@ -74,17 +84,13 @@ else if (type.equalsIgnoreCase("geometry")){ type = "Geometry"; columnType = "geometry(GeometryZ)"; } - else if (type.equalsIgnoreCase("password")){ - //type = "String"; - columnType = "text"; - } else{ //Model? if (type.endsWith("[]")){ //Array of models String modelName = type.substring(0, type.length()-2); - type = "ArrayList<" + modelName + ">"; + type = "ArrayList<" + Utils.capitalize(modelName) + ">"; } else{ //Single model From 9fc7f52394c598d5e571763e3fae475c0ba274fb Mon Sep 17 00:00:00 2001 From: pborissow Date: Tue, 26 Mar 2024 13:56:22 -0400 Subject: [PATCH 08/16] Improved support for models that implement "java.security.Principal", switched default JTS to "org.locationtech.jts", and added support for arrays in the Model class --- src/javaxt/orm/Model.java | 126 +++++++++++++++++++++++++++----------- 1 file changed, 91 insertions(+), 35 deletions(-) diff --git a/src/javaxt/orm/Model.java b/src/javaxt/orm/Model.java index ed9eb8a..942fae3 100644 --- a/src/javaxt/orm/Model.java +++ b/src/javaxt/orm/Model.java @@ -240,9 +240,34 @@ public String getJavaCode(){ TreeSet includes = new TreeSet<>(); + + //Special case for models that implement java.security.Principal + boolean hasNameField = false; + String getSecurityPrincipalName = ""; + if (implementations.contains("java.security.Principal")){ + + //Check if fields have a name field + for (Field field : fields){ + if (field.getName().equalsIgnoreCase("name")){ + hasNameField = true; + break; + } + } + + //If no name field is found, we'll need to add a public getName() + if (!hasNameField){ + getSecurityPrincipalName += " public String getName(){\r\n"; + getSecurityPrincipalName += " return null;\r\n"; + getSecurityPrincipalName += " }\r\n\r\n"; + } + } + + + + //Loop through all the fields and generate java code for (int i=0; i Date: Tue, 26 Mar 2024 14:00:19 -0400 Subject: [PATCH 09/16] Updated dependencies in pom.xml --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 521ad3c..7bbfb54 100644 --- a/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ javaxt javaxt-core - 2.1.5 + 2.1.7 org.openjdk.nashorn From ae43f5b7fc60330fc2db3ec0f7dcea24f00e19e5 Mon Sep 17 00:00:00 2001 From: pborissow Date: Tue, 26 Mar 2024 14:08:56 -0400 Subject: [PATCH 10/16] Updated copyright date in the license --- LICENSE.TXT | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.TXT b/LICENSE.TXT index 50147b1..f8d7956 100644 --- a/LICENSE.TXT +++ b/LICENSE.TXT @@ -1,4 +1,4 @@ -Copyright (c) 2006-2023, Peter Borissow +Copyright (c) 2006-2024, Peter Borissow Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 6103e4af7a1e870473397ab147324c6eb3992153 Mon Sep 17 00:00:00 2001 From: pborissow Date: Mon, 1 Jul 2024 16:56:15 -0400 Subject: [PATCH 11/16] Fixed bug setting field length introduced in a previous release in the Field class --- src/javaxt/orm/Field.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/javaxt/orm/Field.java b/src/javaxt/orm/Field.java index 131fac0..c0fd7a0 100644 --- a/src/javaxt/orm/Field.java +++ b/src/javaxt/orm/Field.java @@ -184,7 +184,8 @@ public void setDefaultValue(Object defaultValue){ public void setLength(int length){ - if (columnType.equalsIgnoreCase("text")){ + if (columnType.equalsIgnoreCase("text") || + columnType.equalsIgnoreCase("varchar")){ columnType = "VARCHAR(" + length + ")"; this.length = length; } From 6835080897e7251d6c215879606255c0c6b0a327 Mon Sep 17 00:00:00 2001 From: pborissow Date: Tue, 8 Oct 2024 13:58:55 -0400 Subject: [PATCH 12/16] Added support for user-defined indexes in the Model class --- src/javaxt/orm/Model.java | 121 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 117 insertions(+), 4 deletions(-) diff --git a/src/javaxt/orm/Model.java b/src/javaxt/orm/Model.java index 942fae3..2cdec1b 100644 --- a/src/javaxt/orm/Model.java +++ b/src/javaxt/orm/Model.java @@ -16,6 +16,7 @@ public class Model { private String name; private TreeSet implementations; private ArrayList fields; + private ArrayList indexes; private static final String template = getTemplate(); private String tableName; private String escapedTableName; @@ -34,6 +35,7 @@ protected Model(String modelName, JSONObject modelInfo, String packageName, Hash this.name = modelName; this.implementations = new TreeSet<>(); this.fields = new ArrayList<>(); + this.indexes = new ArrayList<>(); this.options = options; this.packageName = packageName; this.tableName = Utils.camelCaseToUnderScore(name).toLowerCase(); @@ -91,7 +93,8 @@ protected Model(String modelName, JSONObject modelInfo, String packageName, Hash JSONArray constraints = modelInfo.get("constraints").toJSONArray(); if (constraints!=null){ for (JSONValue constraint : constraints){ - String fieldName = constraint.get("name").toString(); + String fieldName = constraint.get("field").toString(); + if (fieldName==null) fieldName = constraint.get("name").toString(); for (Field field : fields){ if (field.getName().equals(fieldName)){ @@ -103,6 +106,32 @@ protected Model(String modelName, JSONObject modelInfo, String packageName, Hash } + //Parse indexes + JSONArray indexes = modelInfo.get("indexes").toJSONArray(); + if (indexes==null) indexes = modelInfo.get("indices").toJSONArray(); + if (indexes!=null){ + for (JSONValue index : indexes){ + + JSONObject idx; + if (index.toObject() instanceof String){ + String fieldName = index.toString(); + idx = new JSONObject(); + idx.set("field", fieldName); + } + else{ + idx = index.toJSONObject(); + if (idx!=null){ + if (idx.has("fields")){ + idx.set("field", idx.remove("fields")); + } + } + } + + if (idx!=null) this.indexes.add(idx); + } + } + + //Parse default values JSONArray defaultValues = modelInfo.get("defaults").toJSONArray(); if (defaultValues!=null){ @@ -1052,14 +1081,30 @@ public String getForeignKeySQL(){ public String getIndexSQL(){ StringBuilder str = new StringBuilder(); String indexPrefix = "IDX_" + tableName.toUpperCase()+ "_"; - Iterator it = fields.iterator(); - while (it.hasNext()){ - Field field = it.next(); + HashMap columnNames = new HashMap<>(); + + //Create a hashmap of indexes using field names as keys + HashMap indexes = new HashMap<>(); + for (JSONObject index : this.indexes){ + String fieldName = index.get("field").toString(); + indexes.put(fieldName, index); + } + + + //Add indexes to foreign key and geo fields + for (Field field : fields){ + if (!field.isArray()){ + ForeignKey foreignKey = field.getForeignKey(); if (foreignKey!=null){ + String columnName = foreignKey.getColumnName().toUpperCase(); String foreignTable = foreignKey.getForeignTable().toUpperCase(); + columnNames.put(field.getName(), columnName); + + + //Automatically index foreign key fields str.append("CREATE INDEX "); str.append(indexPrefix); str.append(foreignTable); @@ -1068,9 +1113,15 @@ public String getIndexSQL(){ str.append("("); str.append(columnName); str.append(");\r\n"); + + indexes.remove(field.getName()); } else{ + String columnName = field.getColumnName().toUpperCase(); + columnNames.put(field.getName(), columnName); + + //Automatically index geospatial fields if (field.getColumnType().startsWith("geo")){ str.append("CREATE INDEX "); str.append(indexPrefix); @@ -1080,6 +1131,8 @@ public String getIndexSQL(){ str.append(" USING GIST("); str.append(columnName); str.append(");\r\n"); + + indexes.remove(field.getName()); } } } @@ -1087,6 +1140,66 @@ public String getIndexSQL(){ //Handled by getDiamondTableSQL() } } + + + + //Add user defined indexes + for (String key : indexes.keySet()){ + JSONObject index = indexes.get(key); + String name = index.get("name").toString(); + String type = index.get("type").toString(); + + + ArrayList columns = new ArrayList<>(); + if (index.get("field").toObject() instanceof String){ + String fieldName = index.get("field").toString(); + String columnName = columnNames.get(fieldName); + if (columnName!=null){ + columns.add(columnName); + } + } + else{ + JSONArray arr = index.get("field").toJSONArray(); + if (arr!=null){ + for (JSONValue v : arr){ + String fieldName = v.toString(); + String columnName = columnNames.get(fieldName); + if (columnName!=null){ + columns.add(columnName); + } + } + } + } + if (columns.isEmpty()) continue; + + + + + + str.append("CREATE "); + if (type!=null) str.append(type + " "); + str.append("INDEX "); + if (name==null){ + str.append(indexPrefix); + for (int i=0; i0) str.append("_"); + str.append(columns.get(i)); + } + } + else{ + str.append(name.toUpperCase()); + } + + str.append(" ON "); + str.append(escapedTableName); + str.append("("); + for (int i=0; i0) str.append(", "); + str.append(columns.get(i)); + } + str.append(");\r\n"); + } + return str.toString(); } From db017858ea8524372810c14094051b0c8490a4db Mon Sep 17 00:00:00 2001 From: pborissow Date: Wed, 9 Oct 2024 12:17:47 -0400 Subject: [PATCH 13/16] Fixed bug creating foreign keys for model fields with the same type as the parent model --- src/javaxt/orm/Field.java | 13 +++++++++++-- src/javaxt/orm/Model.java | 4 ++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/javaxt/orm/Field.java b/src/javaxt/orm/Field.java index c0fd7a0..a12d54d 100644 --- a/src/javaxt/orm/Field.java +++ b/src/javaxt/orm/Field.java @@ -26,7 +26,7 @@ public class Field { //************************************************************************** /** Creates a new instance of this class. */ - protected Field(String name, String type){ + protected Field(String name, String type, Model model){ this.name = name; this.columnName = Utils.camelCaseToUnderScore(name); @@ -96,8 +96,17 @@ else if (type.equalsIgnoreCase("geometry")){ else{ //Single model columnName = columnName + "_id"; - foreignKey = new ForeignKey(columnName, type); columnType = "bigint"; + + //Typically, when we have a model field we want to create a + //foreign key to tie the field to the model. The only exception + //is if the model field references the parent model - which is + //very rare (most models don't have a model field with the same + //type). + if (!type.equals(model.getName())){ + foreignKey = new ForeignKey(columnName, type); + } + } } diff --git a/src/javaxt/orm/Model.java b/src/javaxt/orm/Model.java index 2cdec1b..7d1850a 100644 --- a/src/javaxt/orm/Model.java +++ b/src/javaxt/orm/Model.java @@ -72,7 +72,7 @@ protected Model(String modelName, JSONObject modelInfo, String packageName, Hash if (name.equalsIgnoreCase("id")) continue; //Create field and update the fields array - Field field = new Field(name, type); + Field field = new Field(name, type, this); addConstraints(field, f.toJSONObject()); this.fields.add(field); } @@ -84,7 +84,7 @@ protected Model(String modelName, JSONObject modelInfo, String packageName, Hash if (hasMany!=null) for (int i=0; i Date: Wed, 9 Oct 2024 12:33:35 -0400 Subject: [PATCH 14/16] Fixed bug introduced in the last commit --- src/javaxt/orm/Field.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/javaxt/orm/Field.java b/src/javaxt/orm/Field.java index a12d54d..b712781 100644 --- a/src/javaxt/orm/Field.java +++ b/src/javaxt/orm/Field.java @@ -18,6 +18,7 @@ public class Field { private boolean unique = false; private Object defaultValue = null; private Integer length; + private boolean isModel = false; private ForeignKey foreignKey; @@ -95,6 +96,7 @@ else if (type.equalsIgnoreCase("geometry")){ } else{ //Single model + isModel = true; columnName = columnName + "_id"; columnType = "bigint"; @@ -142,7 +144,7 @@ public boolean isLastModifiedDate(){ } public boolean isModel(){ - return foreignKey!=null; + return isModel; } public boolean isArray(){ From ea30b4c04f2ba3857aced89eadef61d127c404f7 Mon Sep 17 00:00:00 2001 From: pborissow Date: Wed, 9 Oct 2024 13:28:24 -0400 Subject: [PATCH 15/16] Improved support for "defaults" --- src/javaxt/orm/Model.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/javaxt/orm/Model.java b/src/javaxt/orm/Model.java index 7d1850a..7b4de08 100644 --- a/src/javaxt/orm/Model.java +++ b/src/javaxt/orm/Model.java @@ -74,6 +74,8 @@ protected Model(String modelName, JSONObject modelInfo, String packageName, Hash //Create field and update the fields array Field field = new Field(name, type, this); addConstraints(field, f.toJSONObject()); + Object defaultValue = f.get("default").toObject(); + field.setDefaultValue(defaultValue); this.fields.add(field); } } @@ -136,7 +138,8 @@ protected Model(String modelName, JSONObject modelInfo, String packageName, Hash JSONArray defaultValues = modelInfo.get("defaults").toJSONArray(); if (defaultValues!=null){ for (JSONValue d : defaultValues){ - String fieldName = d.get("name").toString(); + String fieldName = d.get("field").toString(); + if (fieldName==null) fieldName = d.get("name").toString(); for (Field field : fields){ if (field.getName().equals(fieldName)){ From 63a767cd62eae8b20fa8e918fa52cd5c2e1128a2 Mon Sep 17 00:00:00 2001 From: pborissow Date: Tue, 4 Mar 2025 07:20:54 -0500 Subject: [PATCH 16/16] Added "integer" keyword to the Field class --- src/javaxt/orm/Field.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/javaxt/orm/Field.java b/src/javaxt/orm/Field.java index b712781..1f607a5 100644 --- a/src/javaxt/orm/Field.java +++ b/src/javaxt/orm/Field.java @@ -32,7 +32,7 @@ protected Field(String name, String type, Model model){ this.columnName = Utils.camelCaseToUnderScore(name); //Set columnType and tweak type as needed - if (type.equalsIgnoreCase("int")){ + if (type.equalsIgnoreCase("int") || type.equalsIgnoreCase("integer")){ type = "Integer"; columnType = "integer"; } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy