/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.query.sql.lang; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.teiid.core.util.StringUtil; import org.teiid.query.sql.proc.AssignmentStatement; import org.teiid.query.sql.proc.Block; import org.teiid.query.sql.proc.BranchingStatement; import org.teiid.query.sql.proc.CommandStatement; import org.teiid.query.sql.proc.CreateProcedureCommand; import org.teiid.query.sql.proc.CreateUpdateProcedureCommand; import org.teiid.query.sql.proc.DeclareStatement; import org.teiid.query.sql.proc.ExceptionExpression; import org.teiid.query.sql.proc.IfStatement; import org.teiid.query.sql.proc.LoopStatement; import org.teiid.query.sql.proc.RaiseErrorStatement; import org.teiid.query.sql.proc.RaiseStatement; import org.teiid.query.sql.proc.ReturnStatement; import org.teiid.query.sql.proc.Statement; import org.teiid.query.sql.proc.TriggerAction; import org.teiid.query.sql.proc.WhileStatement; import org.teiid.query.sql.symbol.AliasSymbol; import org.teiid.query.sql.symbol.CaseExpression; import org.teiid.query.sql.symbol.Constant; import org.teiid.query.sql.symbol.DerivedColumn; import org.teiid.query.sql.symbol.ElementSymbol; import org.teiid.query.sql.symbol.ExpressionSymbol; import org.teiid.query.sql.symbol.Function; import org.teiid.query.sql.symbol.GroupSymbol; import org.teiid.query.sql.symbol.JSONObject; import org.teiid.query.sql.symbol.MultipleElementSymbol; import org.teiid.query.sql.symbol.QueryString; import org.teiid.query.sql.symbol.Reference; import org.teiid.query.sql.symbol.ScalarSubquery; import org.teiid.query.sql.symbol.SearchedCaseExpression; import org.teiid.query.sql.symbol.Symbol; import org.teiid.query.sql.symbol.TextLine; import org.teiid.query.sql.symbol.WindowSpecification; import org.teiid.query.sql.symbol.XMLAttributes; import org.teiid.query.sql.symbol.XMLElement; import org.teiid.query.sql.symbol.XMLForest; import org.teiid.query.sql.symbol.XMLNamespaces; import org.teiid.query.sql.symbol.XMLParse; import org.teiid.query.sql.symbol.XMLQuery; import org.teiid.query.sql.symbol.XMLSerialize; import org.teiid.query.sql.symbol.v7.Aggregate7Symbol; import org.teiid.query.sql.symbol.v7.Window7Function; import org.teiid.query.sql.symbol.v8.Aggregate8Symbol; import org.teiid.query.sql.symbol.v8.Window8Function; /** * */ @SuppressWarnings( {"javadoc", "nls"} ) public class CloneGenerator { private static final String SEMI_COLON = ";"; private static final String CLONE = "clone"; private static final String RETURN = "return"; private static final String CONSTRUCTOR_PARAMS = "(getTeiidVersion(), this.id)"; private static final String NEW = "new"; private static final String EQUALS = "="; private static final String OVERRIDE = "@Override"; private static final String TAB = " "; private static final String OPEN_BRACE = "{"; private static final String END_BRACE = "}"; private static final String NEWLINE = "\n"; private static final String PUBLIC = "public"; private static final String SPACE = " "; private static final String CLONE_METHOD = "clone()"; private static final String GET = "get"; private static final String IS = "is"; private static final String DOT = StringUtil.Constants.DOT; private static final String OPEN_BRACKET = "("; private static final String CLOSE_BRACKET = ")"; private static final String IF = "if"; private static final String NOT_NULL = "!= null"; private static final String DIRECTORY = "/home/phantomjinx/programming/java/tdesigner/git/plugins/teiid/org.teiid.runtime.client/engine/"; private static final String JAVA = ".java"; private static final List<Class<?>> CLASS_LIST = new ArrayList<Class<?>>(); private static final List<Class<?>> NON_CLONE_CLASSES = new ArrayList<Class<?>>(); private final Map<Class<?>, File> classCache = new HashMap<Class<?>, File>(); static { NON_CLONE_CLASSES.add(Boolean.class); NON_CLONE_CLASSES.add(String.class); NON_CLONE_CLASSES.add(Integer.class); NON_CLONE_CLASSES.add(Double.class); NON_CLONE_CLASSES.add(Float.class); NON_CLONE_CLASSES.add(SourceHint.class); CLASS_LIST.add(Aggregate7Symbol.class); CLASS_LIST.add(Aggregate8Symbol.class); CLASS_LIST.add(AliasSymbol.class); CLASS_LIST.add(Alter.class); CLASS_LIST.add(ArrayTable.class); CLASS_LIST.add(AssignmentStatement.class); CLASS_LIST.add(BetweenCriteria.class); CLASS_LIST.add(Block.class); CLASS_LIST.add(BranchingStatement.class); CLASS_LIST.add(CaseExpression.class); CLASS_LIST.add(Command.class); CLASS_LIST.add(CommandStatement.class); CLASS_LIST.add(CompareCriteria.class); CLASS_LIST.add(CompoundCriteria.class); CLASS_LIST.add(Constant.class); CLASS_LIST.add(CreateProcedureCommand.class); CLASS_LIST.add(CreateUpdateProcedureCommand.class); CLASS_LIST.add(Criteria.class); CLASS_LIST.add(CriteriaSelector.class); CLASS_LIST.add(DeclareStatement.class); CLASS_LIST.add(Delete.class); CLASS_LIST.add(DerivedColumn.class); CLASS_LIST.add(Drop.class); CLASS_LIST.add(DynamicCommand.class); CLASS_LIST.add(ElementSymbol.class); CLASS_LIST.add(ExceptionExpression.class); CLASS_LIST.add(ExistsCriteria.class); CLASS_LIST.add(ExpressionCriteria.class); CLASS_LIST.add(ExpressionSymbol.class); CLASS_LIST.add(FromClause.class); CLASS_LIST.add(From.class); CLASS_LIST.add(Function.class); CLASS_LIST.add(GroupBy.class); CLASS_LIST.add(GroupSymbol.class); CLASS_LIST.add(HasCriteria.class); CLASS_LIST.add(IfStatement.class); CLASS_LIST.add(Insert.class); CLASS_LIST.add(Into.class); CLASS_LIST.add(IsNullCriteria.class); CLASS_LIST.add(JoinPredicate.class); CLASS_LIST.add(JoinType.class); CLASS_LIST.add(JSONObject.class); CLASS_LIST.add(Limit.class); CLASS_LIST.add(LoopStatement.class); CLASS_LIST.add(MatchCriteria.class); CLASS_LIST.add(MultipleElementSymbol.class); CLASS_LIST.add(NamespaceItem.class); CLASS_LIST.add(Node.class); CLASS_LIST.add(NotCriteria.class); CLASS_LIST.add(ObjectColumn.class); CLASS_LIST.add(ObjectTable.class); CLASS_LIST.add(Option.class); CLASS_LIST.add(OrderByItem.class); CLASS_LIST.add(OrderBy.class); CLASS_LIST.add(ProjectedColumn.class); CLASS_LIST.add(QueryCommand.class); CLASS_LIST.add(Query.class); CLASS_LIST.add(QueryString.class); CLASS_LIST.add(RaiseErrorStatement.class); CLASS_LIST.add(RaiseStatement.class); CLASS_LIST.add(Reference.class); CLASS_LIST.add(ReturnStatement.class); CLASS_LIST.add(ScalarSubquery.class); CLASS_LIST.add(SearchedCaseExpression.class); CLASS_LIST.add(Select.class); CLASS_LIST.add(SetClause.class); CLASS_LIST.add(SetClauseList.class); CLASS_LIST.add(SetCriteria.class); CLASS_LIST.add(SetQuery.class); CLASS_LIST.add(SimpleNode.class); CLASS_LIST.add(Statement.class); CLASS_LIST.add(StoredProcedure.class); CLASS_LIST.add(SubqueryCompareCriteria.class); CLASS_LIST.add(SubqueryFromClause.class); CLASS_LIST.add(SubquerySetCriteria.class); CLASS_LIST.add(Symbol.class); CLASS_LIST.add(TextColumn.class); CLASS_LIST.add(TextLine.class); CLASS_LIST.add(TextTable.class); CLASS_LIST.add(TranslateCriteria.class); CLASS_LIST.add(TriggerAction.class); CLASS_LIST.add(UnaryFromClause.class); CLASS_LIST.add(Update.class); CLASS_LIST.add(Window7Function.class); CLASS_LIST.add(Window8Function.class); CLASS_LIST.add(WhileStatement.class); CLASS_LIST.add(WindowSpecification.class); CLASS_LIST.add(WithQueryCommand.class); CLASS_LIST.add(XMLAttributes.class); CLASS_LIST.add(XMLColumn.class); CLASS_LIST.add(XMLElement.class); CLASS_LIST.add(XMLForest.class); CLASS_LIST.add(XMLNamespaces.class); CLASS_LIST.add(XMLParse.class); CLASS_LIST.add(XMLQuery.class); CLASS_LIST.add(XMLSerialize.class); CLASS_LIST.add(XMLTable.class); CLASS_LIST.add(Create.class); } private void cacheASTClasses() { for (Class<?> klazz : CLASS_LIST) { String packagePath = klazz.getPackage().getName(); packagePath = packagePath.replaceAll("\\" + DOT, File.separator); StringBuffer fileName = new StringBuffer(); fileName.append(packagePath); fileName.append(File.separator); if (klazz.getSimpleName().contains("7")) { fileName.append("v7"); fileName.append(File.separator); } else if (klazz.getSimpleName().contains("8")) { fileName.append("v8"); fileName.append(File.separator); } fileName.append(klazz.getSimpleName()); fileName.append(JAVA); File jFile = new File(DIRECTORY, fileName.toString()); if (! jFile.exists()) throw new RuntimeException("The class file " + jFile.getAbsolutePath() + " does not exist"); classCache.put(klazz, jFile); } } /** * @param key * @return */ private StringBuffer createCloneMethod(Class<?> klazz) { StringBuffer buffer = new StringBuffer(NEWLINE); String className = klazz.getSimpleName(); buffer.append(TAB); buffer.append(OVERRIDE); buffer.append(NEWLINE); buffer.append(TAB); buffer.append(PUBLIC); buffer.append(SPACE); buffer.append(className); buffer.append(SPACE); buffer.append(CLONE_METHOD); buffer.append(SPACE); buffer.append(OPEN_BRACE); buffer.append(NEWLINE); buffer.append(TAB); buffer.append(TAB); buffer.append(className); buffer.append(SPACE); buffer.append(CLONE); buffer.append(SPACE); buffer.append(EQUALS); buffer.append(SPACE); buffer.append(NEW); buffer.append(SPACE); buffer.append(className); buffer.append(CONSTRUCTOR_PARAMS); buffer.append(SEMI_COLON); buffer.append(NEWLINE); buffer.append(NEWLINE); for (Method method : klazz.getMethods()) { String methodName = method.getName(); if (! methodName.startsWith("set")) continue; Class<?>[] params = method.getParameterTypes(); String fieldName = methodName.substring(3); String getter = GET + fieldName; if (isBoolean(params[0])) getter = IS + fieldName; // Should only be 1 parameter boolean hasNonCloneParam = false; for (Class<?> nonCloneClass : NON_CLONE_CLASSES) { if (nonCloneClass.getSimpleName().equalsIgnoreCase(params[0].getSimpleName())) { hasNonCloneParam = true; break; } } // check the param is not an enum if (! hasNonCloneParam && params[0].isEnum()) { hasNonCloneParam = true; } if (! isBoolean(params[0])) { buffer.append(TAB); buffer.append(TAB); buffer.append(IF); buffer.append(OPEN_BRACKET); buffer.append(getter); buffer.append(OPEN_BRACKET); buffer.append(CLOSE_BRACKET); buffer.append(SPACE); buffer.append(NOT_NULL); buffer.append(CLOSE_BRACKET); buffer.append(NEWLINE); buffer.append(TAB); } buffer.append(TAB); buffer.append(TAB); buffer.append(CLONE); buffer.append(DOT); buffer.append(methodName); buffer.append(OPEN_BRACKET); buffer.append(getter); buffer.append(OPEN_BRACKET); buffer.append(CLOSE_BRACKET); if(! hasNonCloneParam) { buffer.append(DOT); buffer.append(CLONE_METHOD); } buffer.append(CLOSE_BRACKET); buffer.append(SEMI_COLON); buffer.append(NEWLINE); } // Return statement buffer.append(NEWLINE); buffer.append(TAB); buffer.append(TAB); buffer.append(RETURN); buffer.append(SPACE); buffer.append(CLONE); buffer.append(SEMI_COLON); buffer.append(NEWLINE); buffer.append(TAB); buffer.append(END_BRACE); buffer.append(NEWLINE); buffer.append(NEWLINE); return buffer; } private boolean isBoolean(Class<?> klazz) { return klazz.getSimpleName().equalsIgnoreCase(Boolean.class.getSimpleName()); } private void writeMethod(StringBuffer method, File jFile) throws Exception { BufferedReader reader = new BufferedReader(new FileReader(jFile)); BufferedWriter writer = null; StringBuffer content = new StringBuffer(); try { String line = null; while ((line = reader.readLine()) != null) { content.append(line); content.append("\n"); } int offset = content.lastIndexOf(END_BRACE); if (offset == -1) throw new RuntimeException("File " + jFile.getName() + " does not contain an accept comment!"); content.insert(offset, method.toString()); writer = new BufferedWriter(new FileWriter(jFile)); writer.write(content.toString()); } finally { reader.close(); if (writer != null) writer.close(); } } public void generate() throws Exception { cacheASTClasses(); for (Entry<Class<?>, File> entry : classCache.entrySet()) { StringBuffer method = createCloneMethod(entry.getKey()); writeMethod(method, entry.getValue()); } } public static void main(String[] args) throws Exception { CloneGenerator cg = new CloneGenerator(); cg.generate(); } }