/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.nbstudio.core.cls; import com.intersys.cache.CacheObject; import com.intersys.classes.CacheRootObject; import com.intersys.classes.Dictionary.ClassDefinition; import com.intersys.classes.Dictionary.ForeignKeyDefinition; import com.intersys.classes.Dictionary.IndexDefinition; import com.intersys.classes.Dictionary.MethodDefinition; import com.intersys.classes.Dictionary.ParameterDefinition; import com.intersys.classes.Dictionary.ProjectionDefinition; import com.intersys.classes.Dictionary.PropertyDefinition; import com.intersys.classes.Dictionary.QueryDefinition; import com.intersys.classes.Dictionary.TriggerDefinition; import com.intersys.classes.Dictionary.UDLTextDefinition; import com.intersys.classes.Dictionary.XDataDefinition; import com.intersys.objects.CacheException; import com.intersys.objects.Database; import com.intersys.objects.Id; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.nio.charset.Charset; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import org.antlr.v4.runtime.ANTLRInputStream; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.Lexer; import org.antlr.v4.runtime.RecognitionException; import org.antlr.v4.runtime.tree.ParseTreeWalker; import org.nbstudio.core.CacheFile; import org.nbstudio.syntax.cls.clsLexer; import org.nbstudio.syntax.cls.clsParser; /** * * @author daimor */ public class ClassFile extends CacheFile { ClassDefinition cls; Charset charset = Charset.forName("UTF-8"); protected CacheObject mInternal; private ClassDefinition methodDef; private ClassDefinition propertyDef; private ClassDefinition triggerDef; private ClassDefinition foreignkeyDef; private ClassDefinition projectionDef; private ClassDefinition indexDef; private ClassDefinition queryDef; private ClassDefinition parameterDef; private ClassDefinition xdataDef; public ClassFile(Database db, String name) throws CacheException { super(db, name); try { if (ClassDefinition._existsId(db, new Id(name))) { cls = (ClassDefinition) ClassDefinition._open(db, new Id(name)); } else { cls = new ClassDefinition(db, name); } Field privateStringField = CacheRootObject.class.getDeclaredField("mInternal"); privateStringField.setAccessible(true); mInternal = (CacheObject) privateStringField.get(cls); methodDef = (ClassDefinition) ClassDefinition.open(db, new Id("%Dictionary.MethodDefinition"), 0); propertyDef = (ClassDefinition) ClassDefinition.open(db, new Id("%Dictionary.PropertyDefinition"), 0); foreignkeyDef = (ClassDefinition) ClassDefinition.open(db, new Id("%Dictionary.ForeignKeyDefinition"), 0); indexDef = (ClassDefinition) ClassDefinition.open(db, new Id("%Dictionary.IndexDefinition"), 0); queryDef = (ClassDefinition) ClassDefinition.open(db, new Id("%Dictionary.QueryDefinition"), 0); parameterDef = (ClassDefinition) ClassDefinition.open(db, new Id("%Dictionary.ParameterDefinition"), 0); triggerDef = (ClassDefinition) ClassDefinition.open(db, new Id("%Dictionary.TriggerDefinition"), 0); projectionDef = (ClassDefinition) ClassDefinition.open(db, new Id("%Dictionary.ProjectionDefinition"), 0); xdataDef = (ClassDefinition) ClassDefinition.open(db, new Id("%Dictionary.XDataDefinition"), 0); projectionDef = (ClassDefinition) ClassDefinition.open(db, new Id("%Dictionary.ProjectionDefinition"), 0); } catch (CacheException | IllegalAccessException | IllegalArgumentException | NoSuchFieldException | SecurityException ex) { ex.printStackTrace(); } } @Override public Date getDate() { return null; } @Override public int getSize() { return -1; } @Override public InputStream open() { ClassText os; ByteArrayInputStream is = null; try { os = new ClassText(cls); is = new ByteArrayInputStream(os.toByteArray()); } catch (CacheException ex) { ex.printStackTrace(); } return is; } @Override public void save(byte[] data) { ANTLRInputStream input = new ANTLRInputStream(new String(data, charset)); Lexer lexer = new clsLexer(input); CommonTokenStream tokens = new CommonTokenStream(lexer); clsParser clsParser = new clsParser(tokens); try { clsParser.ProgContext prog = clsParser.prog(); ParseTreeWalker walker = new ParseTreeWalker(); CLSParserListerer4Save listener = new CLSParserListerer4Save(clsParser, db, cls); walker.walk(listener, prog); cls._save(); db.utilities().compileCacheClass(getName(), "cdfk-u"); } catch (CacheException | RecognitionException ex) { System.out.println("SaveException: " + ex.getLocalizedMessage()); // ex.printStackTrace(); } } final class ClassText extends ByteArrayOutputStream { ClassDefinition cls; public ClassText(ClassDefinition cls) throws CacheException { if (cls == null) { return; } this.cls = cls; // cls._reload(); writeParensValue("Include %s\n\n", cls.getIncludeCode()); writeParensValue("Import %s\n\n", cls.getImport()); writeParensValue("IncludeGenerator %s\n\n", cls.getIncludeGenerator()); writeDescription(cls.getDescription()); printf("Class %s", cls.getName()); writeParensValue(" Extends %s", cls.getSuper()); // Class properties List<String> clsProperties = new ArrayList<>(); /// boolean's properties com.intersys.cache.Dataholder tmpRes; String[] boolProps = {"Abstract", "DdlAllowed", "Final", "Hidden", "ProcedureBlock", "SqlRowIdPrivate"}; for (String propName : boolProps) { if (propIsDefined(propName) && ((tmpRes = propGet(propName)) != null)) { clsProperties.add((tmpRes.getBoolean() ? "" : "Not ") + propName); } } /// string's properties String[] stringProps = { "ClassType", "ClientDataType", "ClientName", "CompileAfter", "DependsOn", "Language", "OdbcType", "Owner", "ServerOnly", "SoapBindingStyle", "SoapBodyUse", "SQLCategory", "SqlRowIdName", "SqlTableName", "StorageStrategy", "ViewQuery"}; for (String propName : stringProps) { if (propIsDefined(propName) && ((tmpRes = propGet(propName)) != null)) { clsProperties.add(propName + " = " + tmpRes.getString()); } } writeBrackets(clsProperties); writeln(); println("{"); List<Object> list = new ArrayList<>(); list.addAll(cls.getProperties().asList()); list.addAll(cls.getMethods().asList()); list.addAll(cls.getParameters().asList()); list.addAll(cls.getIndices().asList()); list.addAll(cls.getForeignKeys().asList()); list.addAll(cls.getXDatas().asList()); list.addAll(cls.getProjections().asList()); list.addAll(cls.getQueries().asList()); list.addAll(cls.getTriggers().asList()); list.addAll(cls.getUDLTexts().asList()); Collections.sort(list, new Comparator<Object>() { @Override public int compare(Object o1, Object o2) { int seqNum1 = 0, seqNum2 = 0; try { seqNum1 = getSeqNumber(o1); seqNum2 = getSeqNumber(o2); } catch (CacheException ex) { } if (seqNum1 > seqNum2) { return 1; } else if (seqNum1 < seqNum2) { return -1; } else { return 0; } } int getSeqNumber(Object obj) throws CacheException { if (obj instanceof PropertyDefinition) { return ((PropertyDefinition) obj).getSequenceNumber(); } else if (obj instanceof ParameterDefinition) { return ((ParameterDefinition) obj).getSequenceNumber(); } else if (obj instanceof MethodDefinition) { return ((MethodDefinition) obj).getSequenceNumber(); } else if (obj instanceof XDataDefinition) { return ((XDataDefinition) obj).getSequenceNumber(); } else if (obj instanceof QueryDefinition) { return ((QueryDefinition) obj).getSequenceNumber(); } else if (obj instanceof TriggerDefinition) { return ((TriggerDefinition) obj).getSequenceNumber(); } else if (obj instanceof UDLTextDefinition) { return ((UDLTextDefinition) obj).getSequenceNumber(); } else if (obj instanceof IndexDefinition) { return ((IndexDefinition) obj).getSequenceNumber(); } else if (obj instanceof ForeignKeyDefinition) { return ((ForeignKeyDefinition) obj).getSequenceNumber(); } else if (obj instanceof ProjectionDefinition) { return ((ProjectionDefinition) obj).getSequenceNumber(); } return 0; } }); int pos = 0; for (Object obj : list) { writeln(); if (obj instanceof PropertyDefinition) { showElement((PropertyDefinition) obj); } else if (obj instanceof UDLTextDefinition) { showElement((UDLTextDefinition) obj); } else if (obj instanceof MethodDefinition) { showElement((MethodDefinition) obj); } else if (obj instanceof ParameterDefinition) { showElement((ParameterDefinition) obj); } else if (obj instanceof XDataDefinition) { showElement((XDataDefinition) obj); } else if (obj instanceof QueryDefinition) { showElement((QueryDefinition) obj); } else if (obj instanceof TriggerDefinition) { showElement((TriggerDefinition) obj); } else if (obj instanceof IndexDefinition) { showElement((IndexDefinition) obj); } else if (obj instanceof ForeignKeyDefinition) { showElement((ForeignKeyDefinition) obj); } else if (obj instanceof ProjectionDefinition) { showElement((ProjectionDefinition) obj); } } println("\n}"); } boolean propIsDefined(String propName) { boolean result = false; try { com.intersys.cache.Dataholder[] args = new com.intersys.cache.Dataholder[0]; com.intersys.cache.Dataholder res = mInternal.runInstanceMethod(propName + "IsDefined", args, Database.RET_PRIM); result = res.getBoolean(); } catch (CacheException ex) { } return result; } com.intersys.cache.Dataholder propGet(String propName) { try { com.intersys.cache.Dataholder[] args = new com.intersys.cache.Dataholder[0]; com.intersys.cache.Dataholder res = mInternal.runInstanceMethod(propName + "Get", args, Database.RET_PRIM); return res; } catch (CacheException ex) { } return null; } void propsAdd(List<String> props, CacheRootObject obj, String propName, Object defaultValue) { try { if (defaultValue instanceof Boolean) { boolean boolRes = CLSUtils.getProperty(obj, propName, (Boolean) defaultValue); if (boolRes) { props.add(propName); } } else if (defaultValue instanceof String) { String stringRes = (String) CLSUtils.getProperty(obj, propName, (String) defaultValue); if ((!stringRes.isEmpty()) && (!defaultValue.equals("\"" + stringRes + "\"")) && (!defaultValue.equals(stringRes))) { if ((obj instanceof PropertyDefinition) && ("SqlComputeCode".equals(propName))) { stringRes = "{" + stringRes + "}"; } else if ((obj instanceof XDataDefinition) && (("SchemaSpec".equals(propName)) || ("SchemaSpec".equals(propName)))) { if (stringRes.contains(":")) { stringRes = "\"" + stringRes + "\""; } } else if ((obj instanceof PropertyDefinition) && ("InitialExpression".equals(propName))) { if ((!stringRes.matches("^\"(.*)\"$")) && ((!stringRes.matches("^\\d*$")))) { stringRes = "{" + stringRes + "}"; } } else if (("PublicList".equals(propName)) && (obj instanceof MethodDefinition)) { if (stringRes.contains(",")) { stringRes = stringRes.replace(",", ", "); stringRes = "(" + stringRes + ")"; } } else if (("Data".equals(propName)) && (obj instanceof IndexDefinition)) { if (stringRes.contains(",")) { stringRes = stringRes.replace(",", ", "); stringRes = "(" + stringRes + ")"; } } props.add(propName + " = " + stringRes); } } } catch (Exception ex) { // System.out.println("propsAdd: " + ex.getMessage()); // ex.printStackTrace(); } } void writeProps(ClassDefinition objDef, CacheRootObject obj, List<String> excludeList) { try { if (objDef == null) { return; } List<String> props = new ArrayList<>(); Map<String, Object> objProps = CLSUtils.getProperties(obj); for (Map.Entry<String, Object> entry : objProps.entrySet()) { String propName = entry.getKey(); Object defaultValue = entry.getValue(); propsAdd(props, obj, propName, defaultValue); } writeBrackets(props); } catch (Exception ex) { } } // void showElement(Object obj) { // } void showElement(PropertyDefinition obj) throws CacheException { writeDescription(obj.getDescription()); String propType = obj.getRelationship() ? "Relationship" : "Property"; printf(propType + " %s", obj.getName()); String collection = obj.getCollection() == null ? "" : obj.getCollection(); writeParensValue(" As " + (collection.isEmpty() ? "" : collection + " of ") + "%s", obj.getType()); writeParameters(CLSUtils.getParameters(obj)); String[] excludeList = {"Aliases", "Identity", "OnDelete", "Relationship", "Collection"}; writeProps(propertyDef, obj, Arrays.asList(excludeList)); writeln(";"); } void showElement(ParameterDefinition obj) throws CacheException { writeDescription(obj.getDescription()); printf("Parameter %s", obj.getName()); String[] excludeList = {"Default", "Expression"}; writeProps(parameterDef, obj, Arrays.asList(excludeList)); if ((obj.getDefault() != null) && (!obj.getDefault().isEmpty())) { String parameterValue = obj.getDefault(); if (!parameterValue.matches("^\\d*$")) { parameterValue = "\"" + parameterValue + "\""; } printf(" = %s", parameterValue); } writeln(";"); } void showElement(MethodDefinition obj) throws CacheException { writeDescription(obj.getDescription()); if (obj.getClassMethod()) { printf("ClassMethod %s", obj.getName()); } else { printf("Method %s", obj.getName()); } writeFormalSpec(obj.getFormalSpec()); writeParensValue(" As %s", obj.getReturnType()); String[] excludeList = {"ClassMethod", "ClientMethod", "ReturnType", "FormalSpec", "Implementation", "Hash"}; writeProps(methodDef, obj, Arrays.asList(excludeList)); writeln(); writeln("{"); writeReader(obj.getImplementationIn()); writeln("}"); } void showElement(XDataDefinition obj) throws CacheException { writeDescription(obj.getDescription()); printf("XData %s", obj.getName()); String[] excludeList = {"Data"}; writeProps(xdataDef, obj, Arrays.asList(excludeList)); writeln(); writeln("{"); writeReader(obj.getDataIn()); writeln("}"); } void showElement(QueryDefinition obj) throws CacheException { writeDescription(obj.getDescription()); printf("Query %s", obj.getName()); writeFormalSpec(obj.getFormalSpec()); printf(" As %s", obj.getType()); writeParameters(CLSUtils.getParameters(obj)); String[] excludeList = {"SqlQuery", "FormalSpec"}; writeProps(queryDef, obj, Arrays.asList(excludeList)); writeln(); writeln("{"); String sqlQuery = (obj.getSqlQuery() == null) ? "" : obj.getSqlQuery(); sqlQuery = Pattern.compile("^(\r?\n)?(.*)(\r?\n)?$", Pattern.DOTALL).matcher(sqlQuery).replaceAll("$2"); write(sqlQuery); writeln("\n}"); } void showElement(TriggerDefinition obj) throws CacheException { writeDescription(obj.getDescription()); printf("Trigger %s", obj.getName()); String[] excludeList = {"Code"}; writeProps(triggerDef, obj, Arrays.asList(excludeList)); writeln(); writeln("{"); write(obj.getCode()); writeln("}"); } void showElement(UDLTextDefinition obj) throws CacheException { writeReader(obj.getContentIn()); } void showElement(IndexDefinition obj) throws CacheException { writeDescription(obj.getDescription()); printf("Index %s", obj.getName()); writeParensValue(" On %s", obj.getProperties()); String[] excludeList = {"Properties"}; writeProps(indexDef, obj, Arrays.asList(excludeList)); writeln(";"); } void showElement(ForeignKeyDefinition obj) throws CacheException { writeDescription(obj.getDescription()); String props = (obj.getProperties() == null) ? "" : obj.getProperties(); String refClass = (obj.getReferencedClass() == null) ? "" : obj.getReferencedClass(); String refKey = (obj.getReferencedKey() == null) ? "" : obj.getReferencedKey(); printf("ForeignKey %s(%s)", obj.getName(), props); printf(" References %s(%s)", refClass, refKey); String[] excludeList = {"Properties", "ReferencedClass", "ReferencedKey"}; writeProps(foreignkeyDef, obj, Arrays.asList(excludeList)); writeln(";"); } void showElement(ProjectionDefinition obj) throws CacheException { writeDescription(obj.getDescription()); printf("Projection %s", obj.getName()); printf(" As %s", obj.getType()); writeParameters(CLSUtils.getParameters(obj)); String[] excludeList = {"Type"}; writeProps(projectionDef, obj, Arrays.asList(excludeList)); writeln(";"); } void writeDescription(String str) { if ((str == null) || (str.isEmpty())) { return; } write("/// "); str = str.replace("\n", "\n/// "); write(str); if (!str.isEmpty()) { writeln(); } } void writeFormalSpec(String str) { if ((str != null) && (!str.isEmpty())) { str = str.replace(",", ", "); str = str.replace(":", " As "); str = str.replace("&", "ByRef "); str = str.replace("*", "Output "); str = str.replace("=", " = "); } else { str = ""; } printf("(%s)", str); } void writeParameters(HashMap<String, String> list) { if ((list == null) || (list.isEmpty())) { return; } StringBuilder sepValueBuilder = new StringBuilder(); for (Map.Entry<String, String> entry : list.entrySet()) { if (sepValueBuilder.length() > 0) { sepValueBuilder.append(", "); } String paramName = entry.getKey(); String paramVal = entry.getValue(); if (paramVal != null) { if (!paramVal.matches("^\\d*$")) { paramVal = paramVal.replaceAll("\"", "\"\""); paramVal = "\"" + paramVal + "\""; } sepValueBuilder.append(paramName); sepValueBuilder.append(" = "); sepValueBuilder.append(paramVal); } else { sepValueBuilder.append(paramName); } } if (sepValueBuilder.length() > 0) { printf("(%s)", sepValueBuilder.toString()); } } void writeBrackets(List<String> list) { if ((list == null) || (list.isEmpty())) { return; } StringBuilder sepValueBuilder = new StringBuilder(); //Looping through the itemsList for (int i = 0; i < list.size() - 1; i++) { String value = list.get(i); //append the value into the builder sepValueBuilder.append(value); sepValueBuilder.append(", "); } sepValueBuilder.append(list.get(list.size() - 1)); if (sepValueBuilder.length() > 0) { printf(" [ %s ]", sepValueBuilder.toString()); } } void writeParensValue(String fmt, String str) { if ((str == null) || (str.isEmpty())) { return; } if (str.contains(",")) { str = str.replace(",", ", "); str = "(" + str + ")"; } printf(fmt, str); } public void printf(String string, Object... args) { write(String.format(string, args)); } public void println(String string, Object... args) { writeln(String.format(string, args)); } public void writeln() { write('\n'); } public void writeln(String string) { write(string + '\n'); } public void write(String string) { try { write(string.getBytes(charset)); // write(string.getBytes()); } catch (IOException ex) { ex.printStackTrace(); } } public void writeReader(Reader isr) { try { BufferedReader buff; isr.reset(); buff = new BufferedReader(isr); String str; while ((str = buff.readLine()) != null) { if (str.isEmpty()) { continue; } writeln(str); } } catch (IOException ex) { ex.printStackTrace(); } } } static class ObjectStream extends ByteArrayOutputStream { public ObjectStream() { } public void write(String string) throws IOException { write(string.getBytes()); } } }