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.impl.groovy.closure; 020 021 import org.crsh.shell.impl.command.spi.Command; 022 import org.crsh.shell.impl.command.spi.CommandException; 023 import org.crsh.shell.impl.command.spi.CommandInvoker; 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 Command<?> 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, Command<?> 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, Command<?> 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 create() throws CommandException { 122 return command.resolveCommand(options, subordinate, subordinateOptions, args).getInvoker(); 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 }