001: /*
002: * The contents of this file are subject to the terms
003: * of the Common Development and Distribution License
004: * (the "License"). You may not use this file except
005: * in compliance with the License.
006: *
007: * You can obtain a copy of the license at
008: * https://jwsdp.dev.java.net/CDDLv1.0.html
009: * See the License for the specific language governing
010: * permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL
013: * HEADER in each file and include the License file at
014: * https://jwsdp.dev.java.net/CDDLv1.0.html If applicable,
015: * add the following below this CDDL HEADER, with the
016: * fields enclosed by brackets "[]" replaced with your
017: * own identifying information: Portions Copyright [yyyy]
018: * [name of copyright owner]
019: */
020:
021: package com.sun.codemodel;
022:
023: import java.util.ArrayList;
024: import java.util.List;
025: import java.util.Collections;
026:
027: /**
028: * A block of Java code, which may contain statements and local declarations.
029: *
030: * <p>
031: * {@link JBlock} contains a large number of factory methods that creates new
032: * statements/declarations. Those newly created statements/declarations are
033: * inserted into the {@link #pos() "current position"}. The position advances
034: * one every time you add a new instruction.
035: */
036: public final class JBlock implements JGenerable, JStatement {
037:
038: /**
039: * Declarations and statements contained in this block.
040: * Either {@link JStatement} or {@link JDeclaration}.
041: */
042: private final List<Object> content = new ArrayList<Object>();
043:
044: /**
045: * Whether or not this block must be braced and indented
046: */
047: private boolean bracesRequired = true;
048: private boolean indentRequired = true;
049:
050: /**
051: * Current position.
052: */
053: private int pos;
054:
055: public JBlock() {
056: this (true, true);
057: }
058:
059: public JBlock(boolean bracesRequired, boolean indentRequired) {
060: this .bracesRequired = bracesRequired;
061: this .indentRequired = indentRequired;
062: }
063:
064: /**
065: * Returns a read-only view of {@link JStatement}s and {@link JDeclaration}
066: * in this block.
067: */
068: public List<Object> getContents() {
069: return Collections.unmodifiableList(content);
070: }
071:
072: private <T> T insert(T statementOrDeclaration) {
073: content.add(pos, statementOrDeclaration);
074: pos++;
075: return statementOrDeclaration;
076: }
077:
078: /**
079: * Gets the current position to which new statements will be inserted.
080: *
081: * For example if the value is 0, newly created instructions will be
082: * inserted at the very beginning of the block.
083: *
084: * @see #pos(int)
085: */
086: public int pos() {
087: return pos;
088: }
089:
090: /**
091: * Sets the current position.
092: *
093: * @return
094: * the old value of the current position.
095: * @throws IllegalArgumentException
096: * if the new position value is illegal.
097: *
098: * @see #pos()
099: */
100: public int pos(int newPos) {
101: int r = pos;
102: if (newPos > content.size() || newPos < 0)
103: throw new IllegalArgumentException();
104: pos = newPos;
105:
106: return r;
107: }
108:
109: /**
110: * Adds a local variable declaration to this block
111: *
112: * @param type
113: * JType of the variable
114: *
115: * @param name
116: * Name of the variable
117: *
118: * @return Newly generated JVar
119: */
120: public JVar decl(JType type, String name) {
121: return decl(JMod.NONE, type, name, null);
122: }
123:
124: /**
125: * Adds a local variable declaration to this block
126: *
127: * @param type
128: * JType of the variable
129: *
130: * @param name
131: * Name of the variable
132: *
133: * @param init
134: * Initialization expression for this variable. May be null.
135: *
136: * @return Newly generated JVar
137: */
138: public JVar decl(JType type, String name, JExpression init) {
139: return decl(JMod.NONE, type, name, init);
140: }
141:
142: /**
143: * Adds a local variable declaration to this block
144: *
145: * @param mods
146: * Modifiers for the variable
147: *
148: * @param type
149: * JType of the variable
150: *
151: * @param name
152: * Name of the variable
153: *
154: * @param init
155: * Initialization expression for this variable. May be null.
156: *
157: * @return Newly generated JVar
158: */
159: public JVar decl(int mods, JType type, String name, JExpression init) {
160: JVar v = new JVar(JMods.forVar(mods), type, name, init);
161: insert(v);
162: bracesRequired = true;
163: indentRequired = true;
164: return v;
165: }
166:
167: /**
168: * Creates an assignment statement and adds it to this block.
169: *
170: * @param lhs
171: * Assignable variable or field for left hand side of expression
172: *
173: * @param exp
174: * Right hand side expression
175: */
176: public JBlock assign(JAssignmentTarget lhs, JExpression exp) {
177: insert(new JAssignment(lhs, exp));
178: return this ;
179: }
180:
181: public JBlock assignPlus(JAssignmentTarget lhs, JExpression exp) {
182: insert(new JAssignment(lhs, exp, "+"));
183: return this ;
184: }
185:
186: /**
187: * Creates an invocation statement and adds it to this block.
188: *
189: * @param expr
190: * JExpression evaluating to the class or object upon which
191: * the named method will be invoked
192: *
193: * @param method
194: * Name of method to invoke
195: *
196: * @return Newly generated JInvocation
197: */
198: public JInvocation invoke(JExpression expr, String method) {
199: JInvocation i = new JInvocation(expr, method);
200: insert(i);
201: return i;
202: }
203:
204: /**
205: * Creates an invocation statement and adds it to this block.
206: *
207: * @param expr
208: * JExpression evaluating to the class or object upon which
209: * the method will be invoked
210: *
211: * @param method
212: * JMethod to invoke
213: *
214: * @return Newly generated JInvocation
215: */
216: public JInvocation invoke(JExpression expr, JMethod method) {
217: return insert(new JInvocation(expr, method));
218: }
219:
220: /**
221: * Creates a static invocation statement.
222: */
223: public JInvocation staticInvoke(JClass type, String method) {
224: return insert(new JInvocation(type, method));
225: }
226:
227: /**
228: * Creates an invocation statement and adds it to this block.
229: *
230: * @param method
231: * Name of method to invoke
232: *
233: * @return Newly generated JInvocation
234: */
235: public JInvocation invoke(String method) {
236: return insert(new JInvocation((JExpression) null, method));
237: }
238:
239: /**
240: * Creates an invocation statement and adds it to this block.
241: *
242: * @param method
243: * JMethod to invoke
244: *
245: * @return Newly generated JInvocation
246: */
247: public JInvocation invoke(JMethod method) {
248: return insert(new JInvocation((JExpression) null, method));
249: }
250:
251: /**
252: * Adds a statement to this block
253: *
254: * @param s
255: * JStatement to be added
256: *
257: * @return This block
258: */
259: public JBlock add(JStatement s) { // ## Needed?
260: insert(s);
261: return this ;
262: }
263:
264: /**
265: * Create an If statement and add it to this block
266: *
267: * @param expr
268: * JExpression to be tested to determine branching
269: *
270: * @return Newly generated conditional statement
271: */
272: public JConditional _if(JExpression expr) {
273: return insert(new JConditional(expr));
274: }
275:
276: /**
277: * Create a For statement and add it to this block
278: *
279: * @return Newly generated For statement
280: */
281: public JForLoop _for() {
282: return insert(new JForLoop());
283: }
284:
285: /**
286: * Create a While statement and add it to this block
287: *
288: * @return Newly generated While statement
289: */
290: public JWhileLoop _while(JExpression test) {
291: return insert(new JWhileLoop(test));
292: }
293:
294: /**
295: * Create a switch/case statement and add it to this block
296: */
297: public JSwitch _switch(JExpression test) {
298: return insert(new JSwitch(test));
299: }
300:
301: /**
302: * Create a Do statement and add it to this block
303: *
304: * @return Newly generated Do statement
305: */
306: public JDoLoop _do(JExpression test) {
307: return insert(new JDoLoop(test));
308: }
309:
310: /**
311: * Create a Try statement and add it to this block
312: *
313: * @return Newly generated Try statement
314: */
315: public JTryBlock _try() {
316: return insert(new JTryBlock());
317: }
318:
319: /**
320: * Create a return statement and add it to this block
321: */
322: public void _return() {
323: insert(new JReturn(null));
324: }
325:
326: /**
327: * Create a return statement and add it to this block
328: */
329: public void _return(JExpression exp) {
330: insert(new JReturn(exp));
331: }
332:
333: /**
334: * Create a throw statement and add it to this block
335: */
336: public void _throw(JExpression exp) {
337: insert(new JThrow(exp));
338: }
339:
340: /**
341: * Create a break statement and add it to this block
342: */
343: public void _break() {
344: _break(null);
345: }
346:
347: public void _break(JLabel label) {
348: insert(new JBreak(label));
349: }
350:
351: /**
352: * Create a label, which can be referenced from
353: * <code>continue</code> and <code>break</code> statements.
354: */
355: public JLabel label(String name) {
356: JLabel l = new JLabel(name);
357: insert(l);
358: return l;
359: }
360:
361: /**
362: * Create a continue statement and add it to this block
363: */
364: public void _continue(JLabel label) {
365: insert(new JContinue(label));
366: }
367:
368: public void _continue() {
369: _continue(null);
370: }
371:
372: /**
373: * Create a sub-block and add it to this block
374: */
375: public JBlock block() {
376: JBlock b = new JBlock();
377: b.bracesRequired = false;
378: b.indentRequired = false;
379: return insert(b);
380: }
381:
382: /**
383: * Creates a "literal" statement directly.
384: *
385: * <p>
386: * Specified string is printed as-is.
387: * This is useful as a short-cut.
388: *
389: * <p>
390: * For example, you can invoke this method as:
391: * <code>directStatement("a=b+c;")</code>.
392: */
393: public JStatement directStatement(final String source) {
394: JStatement s = new JStatement() {
395: public void state(JFormatter f) {
396: f.p(source).nl();
397: }
398: };
399: add(s);
400: return s;
401: }
402:
403: public void generate(JFormatter f) {
404: if (bracesRequired)
405: f.p('{').nl();
406: if (indentRequired)
407: f.i();
408: generateBody(f);
409: if (indentRequired)
410: f.o();
411: if (bracesRequired)
412: f.p('}');
413: }
414:
415: void generateBody(JFormatter f) {
416: for (Object o : content) {
417: if (o instanceof JDeclaration)
418: f.d((JDeclaration) o);
419: else
420: f.s((JStatement) o);
421: }
422: }
423:
424: /**
425: * Creates an enhanced For statement based on j2se 1.5 JLS
426: * and add it to this block
427: *
428: * @return Newly generated enhanced For statement per j2se 1.5
429: * specification
430: */
431: public JForEach forEach(JType varType, String name,
432: JExpression collection) {
433: return insert(new JForEach(varType, name, collection));
434:
435: }
436:
437: public void state(JFormatter f) {
438: f.g(this);
439: if (bracesRequired)
440: f.nl();
441: }
442:
443: }
|