EMMA Coverage Report (generated Mon Oct 17 05:41:20 EDT 2011)
[all classes][org.jclouds.scriptbuilder.domain]

COVERAGE SUMMARY FOR SOURCE FILE [SwitchArg.java]

nameclass, %method, %block, %line, %
SwitchArg.java100% (1/1)100% (8/8)95%  (329/346)89%  (55.9/63)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class SwitchArg100% (1/1)100% (8/8)95%  (329/346)89%  (55.9/63)
equals (Object): boolean 100% (1/1)66%  (29/44)53%  (8/15)
hashCode (): int 100% (1/1)92%  (24/26)98%  (4.9/5)
<static initializer> 100% (1/1)100% (19/19)100% (3/3)
SwitchArg (int, Map): void 100% (1/1)100% (12/12)100% (4/4)
accept (StatementVisitor): void 100% (1/1)100% (17/17)100% (3/3)
addArgValidation (StringBuilder, OsFamily): void 100% (1/1)100% (56/56)100% (7/7)
functionDependencies (OsFamily): Iterable 100% (1/1)100% (23/23)100% (4/4)
render (OsFamily): String 100% (1/1)100% (149/149)100% (22/22)

1/**
2 * Licensed to jclouds, Inc. (jclouds) under one or more
3 * contributor license agreements.  See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership.  jclouds licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License.  You may obtain a copy of the License at
9 *
10 *   http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied.  See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19package org.jclouds.scriptbuilder.domain;
20 
21import static com.google.common.base.Preconditions.checkNotNull;
22 
23import java.util.List;
24import java.util.Map;
25import java.util.Map.Entry;
26 
27import org.jclouds.scriptbuilder.util.Utils;
28 
29import com.google.common.annotations.VisibleForTesting;
30import com.google.common.base.Joiner;
31import com.google.common.base.Splitter;
32import com.google.common.collect.ImmutableMap;
33import com.google.common.collect.Iterables;
34import com.google.common.collect.Lists;
35 
36/**
37 * Statement used in a shell script
38 * 
39 * @author Adrian Cole
40 */
41public class SwitchArg implements Statement, AcceptsStatementVisitor {
42 
43   private static final String INDENT = "   ";
44 
45   public static final Map<OsFamily, String> OS_TO_SWITCH_PATTERN = ImmutableMap.of(OsFamily.UNIX, "case ${arg} in\n",
46            OsFamily.WINDOWS, "goto CASE_%{arg}\r\n");
47 
48   public static final Map<OsFamily, String> OS_TO_END_SWITCH_PATTERN = ImmutableMap.of(OsFamily.UNIX, "esac\n",
49            OsFamily.WINDOWS, ":END_SWITCH\r\n");
50 
51   public static final Map<OsFamily, String> OS_TO_CASE_PATTERN = ImmutableMap.of(OsFamily.UNIX,
52            "{value})\n{action};;\n", OsFamily.WINDOWS, ":CASE_{value}\r\n{action}GOTO END_SWITCH\r\n");
53 
54   private final int arg;
55 
56   private final Map<String, Statement> valueToActions;
57 
58   /**
59    * Generates a switch statement based on {@code arg}. If its value is found to be a key in
60    * {@code valueToActions}, the corresponding action is invoked.
61    * 
62    * <p/>
63    * Ex. arg is {@code 1} - the first argument to the script<br/>
64    * and valueToActions is {"start" -> "echo hello", "stop" -> "echo goodbye"}<br/>
65    * the script created will respond accordingly:<br/>
66    * {@code ./script start }<br/>
67    * << returns hello<br/>
68    * {@code ./script stop }<br/>
69    * << returns goodbye<br/>
70    * 
71    * @param arg
72    *           - shell arg to switch on
73    * @param valueToActions
74    *           - case statements, if the value of the arg matches a key, the corresponding value
75    *           will be invoked.
76    */
77   public SwitchArg(int arg, Map<String, Statement> valueToActions) {
78      this.arg = arg;
79      this.valueToActions = checkNotNull(valueToActions, "valueToActions");
80   }
81 
82   public String render(OsFamily family) {
83      StringBuilder switchClause = new StringBuilder();
84      addArgValidation(switchClause, family);
85      switchClause.append(Utils.replaceTokens(OS_TO_SWITCH_PATTERN.get(family), ImmutableMap.of("arg", arg + "")));
86 
87      for (Entry<String, Statement> entry : valueToActions.entrySet()) {
88 
89         StringBuilder actionBuilder = new StringBuilder();
90         boolean shouldIndent = true;
91         boolean inRunScript = false;
92         boolean inCreateFile = false;
93         for (String line : Splitter.on(ShellToken.LF.to(family)).split(entry.getValue().render(family))) {
94            if (shouldIndent)
95               actionBuilder.append(INDENT);
96            actionBuilder.append(line).append(ShellToken.LF.to(family));
97            if (line.indexOf(CreateRunScript.MARKER) != -1) {
98               inRunScript = inRunScript ? false : true;
99 
100            }
101            if (line.indexOf(AppendFile.MARKER) != -1) {
102               inCreateFile = inCreateFile ? false : true;
103            }
104            shouldIndent = !inCreateFile && !inRunScript;
105 
106         }
107         actionBuilder.delete(actionBuilder.lastIndexOf(ShellToken.LF.to(family)), actionBuilder.length());
108         switchClause.append(Utils.replaceTokens(OS_TO_CASE_PATTERN.get(family), ImmutableMap.of("value", entry
109                  .getKey(), "action", actionBuilder.toString())));
110      }
111 
112      switchClause.append(OS_TO_END_SWITCH_PATTERN.get(family));
113      return switchClause.toString();
114   }
115 
116   @VisibleForTesting
117   void addArgValidation(StringBuilder switchClause, OsFamily family) {
118      if (family.equals(OsFamily.WINDOWS)) {
119         for (String value : valueToActions.keySet()) {
120            switchClause.append("if not \"%").append(arg).append(String.format("\" == \"%s\" ", value));
121         }
122         switchClause.append("(\r\n   set EXCEPTION=bad argument: %").append(arg).append(" not in ");
123         switchClause.append(Joiner.on(" ").join(valueToActions.keySet()));
124         switchClause.append("\r\n   goto abort\r\n)\r\n");
125      }
126   }
127 
128   @Override
129   public Iterable<String> functionDependencies(OsFamily family) {
130      List<String> functions = Lists.newArrayList();
131      for (Statement statement : valueToActions.values()) {
132         Iterables.addAll(functions, statement.functionDependencies(family));
133      }
134      return functions;
135   }
136 
137   @Override
138   public int hashCode() {
139      final int prime = 31;
140      int result = 1;
141      result = prime * result + arg;
142      result = prime * result + ((valueToActions == null) ? 0 : valueToActions.hashCode());
143      return result;
144   }
145 
146   @Override
147   public boolean equals(Object obj) {
148      if (this == obj)
149         return true;
150      if (obj == null)
151         return false;
152      if (getClass() != obj.getClass())
153         return false;
154      SwitchArg other = (SwitchArg) obj;
155      if (arg != other.arg)
156         return false;
157      if (valueToActions == null) {
158         if (other.valueToActions != null)
159            return false;
160      } else if (!valueToActions.equals(other.valueToActions))
161         return false;
162      return true;
163   }
164 
165   @Override
166   public void accept(StatementVisitor visitor) {
167      for (Statement statement : valueToActions.values()) {
168         visitor.visit(statement);
169      }
170   }
171}

[all classes][org.jclouds.scriptbuilder.domain]
EMMA 2.0.5312 (C) Vladimir Roubtsov