001 /*
002 * Copyright (C) 2012 eXo Platform SAS.
003 *
004 * This is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU Lesser General Public License as
006 * published by the Free Software Foundation; either version 2.1 of
007 * the License, or (at your option) any later version.
008 *
009 * This software is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public
015 * License along with this software; if not, write to the Free
016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018 */
019 package org.crsh.lang.groovy.closure;
020
021 import org.crsh.shell.impl.command.spi.CommandCreationException;
022 import org.crsh.shell.impl.command.spi.CommandInvoker;
023 import org.crsh.shell.impl.command.spi.ShellCommand;
024
025 import java.util.ArrayList;
026 import java.util.HashMap;
027 import java.util.Iterator;
028 import java.util.List;
029 import java.util.Map;
030
031 /** @author Julien Viet */
032 class CommandElement extends PipeLineElement {
033
034 /** . */
035 final String commandName;
036
037 /** . */
038 final ShellCommand<?> command;
039
040 /** . */
041 final Map<String, Object> options;
042
043 /** . */
044 final String subordinate;
045
046 /** . */
047 final Map<String, Object> subordinateOptions;
048
049 /** . */
050 final List<Object> args;
051
052 public CommandElement(String commandName, ShellCommand<?> command, Map<String, Object> options) {
053 this.commandName = commandName;
054 this.command = command;
055 this.options = options;
056 this.subordinate = null;
057 this.subordinateOptions = null;
058 this.args = null;
059 }
060
061 public CommandElement subordinate(String name) {
062 return new CommandElement(
063 this.commandName + "." + name,
064 this.command,
065 this.options,
066 name,
067 this.subordinateOptions,
068 this.args);
069 }
070
071 public CommandElement merge(Map<String, ?> options, List<?> arguments) {
072
073 // We merge options
074 Map<String, Object> nextOptions;
075 if (subordinate == null) {
076 nextOptions = this.options;
077 } else {
078 nextOptions = this.subordinateOptions;
079 }
080 if (options != null && options.size() > 0) {
081 if (nextOptions == null) {
082 nextOptions = new HashMap<String, Object>();
083 } else {
084 nextOptions = new HashMap<String, Object>(options);
085 }
086 for (Map.Entry<?, ?> arg : options.entrySet()) {
087 nextOptions.put(arg.getKey().toString(), arg.getValue());
088 }
089 }
090
091 // We merge arguments
092 List<Object> nextArgs;
093 if (arguments != null) {
094 nextArgs = new ArrayList<Object>();
095 if (this.args != null) {
096 nextArgs.addAll(this.args);
097 }
098 nextArgs.addAll(arguments);
099 } else {
100 nextArgs = this.args;
101 }
102
103 //
104 if (subordinate == null) {
105 return new CommandElement(this.commandName, this.command, nextOptions, null, null, nextArgs);
106 } else {
107 return new CommandElement(this.commandName, this.command, this.options, subordinate, nextOptions, nextArgs);
108 }
109 }
110
111 private CommandElement(String commandName, ShellCommand<?> command, Map<String, Object> options, String subordinate, Map<String, Object> subordinateOptions, List<Object> args) {
112 this.commandName = commandName;
113 this.command = command;
114 this.options = options;
115 this.subordinate = subordinate;
116 this.subordinateOptions = subordinateOptions;
117 this.args = args;
118 }
119
120 @Override
121 CommandInvoker make() throws CommandCreationException {
122 return command.resolveInvoker(options, subordinate, subordinateOptions, args);
123 }
124
125 private void format(Object o, StringBuilder buffer) {
126 if (o instanceof String) {
127 buffer.append('"').append(o).append('"');
128 } else if (o instanceof Boolean || o instanceof Number) {
129 buffer.append(o);
130 } else {
131 buffer.append('<').append(o).append('>');
132 }
133 }
134
135 void toString(StringBuilder buffer) {
136 buffer.append(commandName);
137 boolean hasOptions = subordinateOptions != null && subordinateOptions.size() > 0;
138 boolean hasArguments = args != null && args.size() > 0;
139 if (hasOptions || hasArguments) {
140 buffer.append(" {");
141 if (hasOptions) {
142 for (Iterator<Map.Entry<String, Object>> i = subordinateOptions.entrySet().iterator();i.hasNext();) {
143 Map.Entry<String, Object> option = i.next();
144 buffer.append(' ').append(option.getKey()).append('=');
145 format(option.getValue(), buffer);
146 if (i.hasNext()) {
147 buffer.append(";");
148 }
149 }
150 if (hasArguments) {
151 buffer.append(";");
152 }
153 }
154 if (hasArguments) {
155 buffer.append(" [");
156 for (Iterator<Object> i = args.iterator();i.hasNext();) {
157 Object arg = i.next();
158 format(arg, buffer);
159 if (i.hasNext()) {
160 buffer.append(", ");
161 }
162 }
163 buffer.append("]");
164 }
165 buffer.append(" }");
166 }
167 }
168 }