001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019: package org.netbeans.modules.sql.framework.codegen.base;
020:
021: import java.util.ArrayList;
022: import java.util.HashMap;
023: import java.util.List;
024: import java.util.Map;
025: import org.apache.velocity.VelocityContext;
026: import org.netbeans.modules.sql.framework.codegen.AbstractGenerator;
027: import org.netbeans.modules.sql.framework.codegen.StatementContext;
028: import org.netbeans.modules.sql.framework.codegen.TemplateBuilder;
029: import org.netbeans.modules.sql.framework.model.SQLCaseOperator;
030: import org.netbeans.modules.sql.framework.model.SQLCondition;
031: import org.netbeans.modules.sql.framework.model.SQLConstants;
032: import org.netbeans.modules.sql.framework.model.SQLObject;
033: import org.netbeans.modules.sql.framework.model.SQLWhen;
034: import com.sun.sql.framework.exception.BaseException;
035:
036: /**
037: * Velocity-based generator that generates SQL Case expressions.
038: *
039: * @author Jonathan Giron
040: * @author Ahimanikya Satapathy
041: * @version $Revision$
042: */
043: public class BaseCaseGenerator extends AbstractGenerator {
044:
045: public String generate(SQLObject obj, StatementContext context)
046: throws BaseException {
047: if (obj == null || getObjectType(obj) != SQLConstants.CASE) {
048: throw new BaseException(
049: "Bad SQLObject type - case expected.");
050: }
051:
052: SQLCaseOperator operator = (SQLCaseOperator) obj;
053: VelocityContext vContext = new VelocityContext();
054:
055: vContext.put("switch", buildSwitchClause(operator, context));
056: vContext
057: .put("whenClauses", buildWhenClauses(operator, context));
058: vContext.put("default", buildDefaultClause(operator, context));
059:
060: String nestedIndent = (String) context
061: .getClientProperty("nestedIndent");
062: vContext.put("nestedIndent",
063: (nestedIndent != null) ? nestedIndent : " ");
064: return TemplateBuilder.generateSql(this .getDB()
065: .getTemplateFileName("caseWhen"), vContext);
066: }
067:
068: /**
069: * Builds appropriate switch clause, if applicable, from the given SQLCaseOperator
070: * instance. DB-specific extensions should override this method to reflect
071: * vendor-specific syntax quirks.
072: *
073: * @param operator SQLCaseOperator to be interrogated
074: * @param context StatementContext to use in evaluating switch clause
075: * @return String representing switch clause, possibly the empty string ("")
076: * @throws BaseException if error occurs during evaluation
077: */
078: protected String buildSwitchClause(SQLCaseOperator operator,
079: StatementContext context) throws BaseException {
080: String switchClause = "";
081:
082: SQLObject condition = operator
083: .getSQLObject(SQLCaseOperator.SWITCH);
084: boolean containsPredicate = condition != null
085: && getObjectType(condition) == SQLConstants.PREDICATE;
086: if (containsPredicate) {
087: switchClause = this .getDB().getGeneratorFactory().generate(
088: condition, context);
089: }
090:
091: return switchClause;
092: }
093:
094: /**
095: * Builds List of mapped when-then clauses to be inserted into the Velocity template
096: * context. DB-specific extensions should override this method to reflect
097: * vendor-specific syntax quirks.
098: *
099: * @param operator SQLCaseOperator to be interrogated
100: * @param context StatementContext to use in evaluating individual when clauses
101: * @return List of Maps containing "when" and "then" clauses
102: * @throws BaseException if error occurs during evaluation
103: */
104: protected List buildWhenClauses(SQLCaseOperator operator,
105: StatementContext context) throws BaseException {
106: SQLObject condition = operator
107: .getSQLObject(SQLCaseOperator.SWITCH);
108: boolean containsPredicate = condition != null
109: && getObjectType(condition) == SQLConstants.PREDICATE;
110:
111: List<SQLWhen> whenObjects = operator.getWhenList();
112: List<Map<String, String>> whenClauses = new ArrayList<Map<String, String>>(
113: whenObjects.size());
114:
115: for (int i = 0; i < operator.getWhenCount(); i++) {
116: SQLWhen when = whenObjects.get(i);
117: SQLCondition wcondition = when.getCondition();
118: if (wcondition == null || containsPredicate) {
119: throw new BaseException("Badly formed case object.");
120: }
121:
122: Map<String, String> whenThen = new HashMap<String, String>(
123: 1);
124: whenThen.put("when", this .getDB().getGeneratorFactory()
125: .generate(wcondition.getRootPredicate(), context));
126: whenThen.put("then", this .getDB().getGeneratorFactory()
127: .generate(when.getSQLObject(SQLWhen.RETURN),
128: context));
129:
130: whenClauses.add(whenThen);
131: }
132:
133: return whenClauses;
134: }
135:
136: /**
137: * Builds appropriate default clause, if applicable, from the given SQLCaseOperator
138: * instance. DB-specific extensions should override this method to reflect
139: * vendor-specific syntax quirks.
140: *
141: * @param operator SQLCaseOperator to be interrogated to obtain appropriate default
142: * clause
143: * @param context StatementContext to use in evaluating default clause
144: */
145: protected String buildDefaultClause(SQLCaseOperator operator,
146: StatementContext context) throws BaseException {
147: String defaultClause = "";
148:
149: SQLObject defaultAction = operator
150: .getSQLObject(SQLCaseOperator.DEFAULT);
151: if (defaultAction != null) {
152: defaultClause = this .getDB().getGeneratorFactory()
153: .generate(defaultAction, context);
154: }
155:
156: return defaultClause;
157: }
158:
159: /**
160: * Resolve Object type if required.
161: *
162: * @param object SQLObject
163: * @return int value of SQLObject type
164: */
165: protected final int getObjectType(SQLObject object) {
166: int type;
167: switch (object.getObjectType()) {
168: case SQLConstants.VISIBLE_PREDICATE:
169: type = SQLConstants.PREDICATE;
170: break;
171: case SQLConstants.VISIBLE_LITERAL:
172: type = SQLConstants.LITERAL;
173: break;
174: default:
175: type = object.getObjectType();
176: }
177:
178: return type;
179: }
180: }
|