protected <STATE, STACKITEM> TraceItem<STATE, STACKITEM> traceToWithPruningStack( IPdaAdapter<STATE, STACKITEM> pda, Iterable<STATE> starts, Iterator<STACKITEM> stack, Predicate<STATE> matches, Predicate<STATE> canPass) { StackItem<STACKITEM> stackItem = createStack(stack); List<TraceItem<STATE, STACKITEM>> current = Lists.newArrayList(); Set<STATE> visited = Sets.newHashSet(starts); TraceItem<STATE, STACKITEM> result = null; for (STATE start : starts) { TraceItem<STATE, STACKITEM> item = new TraceItem<STATE, STACKITEM>(null, start, stackItem); // if (matches.apply(start)) // result = item; current.add(item); } int counter = stackItem.size() * -1; while (current.size() > 0 && counter < visited.size()) { List<TraceItem<STATE, STACKITEM>> newCurrent = Lists.newArrayList(); for (TraceItem<STATE, STACKITEM> trace : current) for (STATE follower : pda.getFollowers(trace.state)) { if (matches.apply(follower)) { TraceItem<STATE, STACKITEM> found = new TraceItem<STATE, STACKITEM>(trace, follower, trace.stackitem); if (found.stackitem == null) return found; if (result == null || result.stackitem.size() > found.stackitem.size()) { result = found; counter = result.stackitem.size() * -1; } else if (result.stackitem.size() == found.stackitem.size() && result.size() > found.size()) { result = found; counter = result.stackitem.size() * -1; } } if (canPass.apply(follower)) { STACKITEM push = pda.getPush(follower); visited.add(follower); if (push != null) { StackItem<STACKITEM> pushed = trace.stackitem.push(push); newCurrent.add(new TraceItem<STATE, STACKITEM>(trace, follower, pushed)); } else { STACKITEM pop = pda.getPop(follower); if (pop != null) { if (trace.stackitem != null && pop == trace.stackitem.peek()) { StackItem<STACKITEM> popped = trace.stackitem.pop(); newCurrent.add(new TraceItem<STATE, STACKITEM>(trace, follower, popped)); } } else newCurrent.add(new TraceItem<STATE, STACKITEM>(trace, follower, trace.stackitem)); } } } current = newCurrent; counter++; } return result; }
/** * @param resourceBody * @param fqn * @return */ public List<IEObjectDescription> findAttributesWithPrefix( ResourceBody resourceBody, QualifiedName fqn) { // Must be configured for the resource containing resourceBody List<IEObjectDescription> result = Lists.newArrayList(); // do meta lookup first as this is made fast via a cache and these are used more frequent // than other parameters (measured). // TODO: VERIFY that empty last segment matches ok // TODO: Make sure that length of match is same number of segments if (metaCache == null) cacheMetaParameters(resourceBody); String fqnLast = fqn.getLastSegment(); for (String name : metaCache.keySet()) if (name.startsWith(fqnLast)) result.add(metaCache.get(name)); result.addAll( findAttributesWithGuard( resourceBody, fqn, null, Lists.<QualifiedName>newArrayList(), true)); return result; }
/** * Find an attribute being a DefinitionArgument, Property, or Parameter for the given type, or a * meta Property or Parameter defined for the type 'Type'. * * @param scopeDetermeningObject * @param fqn * @return */ protected List<IEObjectDescription> findAttributes( EObject scopeDetermeningObject, QualifiedName fqn, PPImportedNamesAdapter importedNames) { List<IEObjectDescription> result = null; // do meta lookup first as this is made fast via a cache and these are used more frequent // than other parameters (measured). if (metaCache == null) cacheMetaParameters(scopeDetermeningObject); IEObjectDescription d = metaCache.get(fqn.getLastSegment()); if (d == null) result = findAttributesWithGuard( scopeDetermeningObject, fqn, importedNames, Lists.<QualifiedName>newArrayList(), false); else result = Lists.newArrayList(d); return result; }
public List<STATE> asList() { List<STATE> result = Lists.newArrayList(); TraceItem<STATE, STACKITEM> current = this; while (current != null) { result.add(current.state); current = current.parent; } Collections.reverse(result); return result; }
@Override public String toString() { List<String> result = Lists.newArrayList(); StackItem<T> current = this; while (current != null) { if (current.value != null) result.add(current.value.toString()); current = current.pop(); } return Join.join(", ", result); }
/** * Adjusts the list of found targets in accordance with the search path for the resource being * linked. This potentially resolves ambiguities (if found result is further away on the path). * May return more than one result, if more than one resolution exist with the same path index. * * @param targets * @return list of descriptions with lowest index. */ private List<IEObjectDescription> searchPathAdjusted(List<IEObjectDescription> targets) { int minIdx = Integer.MAX_VALUE; List<IEObjectDescription> result = Lists.newArrayList(); for (IEObjectDescription d : targets) { int idx = searchPath.searchIndexOf(d); if (idx < 0) continue; // not found, skip if (idx < minIdx) { minIdx = idx; result.clear(); // forget worse result } // only remember if equal to best found so far if (idx <= minIdx) result.add(d); } return result; }
/** * Verify that only instances that fail cause dependency failures. In other words, when run, this * test should show: passed = [f#1 f#3 g#1 g#3], failed = [f#2], skipped = [g#2] * * @author Cedric Beust <*****@*****.**> */ public class InstanceSkipSampleTest { private int m_n; public static List<String> m_list = Lists.newArrayList(); @Factory(dataProvider = "dp") public InstanceSkipSampleTest(int n) { m_n = n; } @DataProvider public static Object[][] dp() { return new Object[][] { new Object[] {1}, new Object[] {2}, new Object[] {3}, }; } @Test public void f() { if (m_n == 2) throw new RuntimeException(); log("f"); } @Test(dependsOnMethods = "f") public void g() { log("g"); } private void log(String s) { m_list.add(s + "#" + m_n); } @Override public String toString() { return "" + m_n; } }
protected List<IEObjectDescription> findExternal( EObject scopeDetermeningObject, QualifiedName fqn, PPImportedNamesAdapter importedNames, boolean prefixMatch, EClass... eClasses) { if (scopeDetermeningObject == null) throw new IllegalArgumentException("scope determening object is null"); if (fqn == null) throw new IllegalArgumentException("name is null"); if (eClasses == null || eClasses.length < 1) throw new IllegalArgumentException("eClass is null or empty"); if (fqn.getSegmentCount() == 1 && "".equals(fqn.getSegment(0))) throw new IllegalArgumentException("FQN has one empty segment"); // Not meaningful to record the fact that an Absolute reference was used as nothing // is named with an absolute FQN (i.e. it is only used to do lookup). final boolean absoluteFQN = fqn.getSegmentCount() > 0 && "".equals(fqn.getSegment(0)); if (importedNames != null) importedNames.add(absoluteFQN ? fqn.skipFirst(1) : fqn); List<IEObjectDescription> targets = Lists.newArrayList(); Resource scopeDetermeningResource = scopeDetermeningObject.eResource(); if (scopeDetermeningResource != resource) { // This is a lookup in the perspective of some other resource IResourceDescriptions descriptionIndex = indexProvider.getResourceDescriptions(scopeDetermeningResource); IResourceDescription descr = descriptionIndex.getResourceDescription(scopeDetermeningResource.getURI()); // GIVE UP (the system is performing a build clean). if (descr == null) return targets; QualifiedName nameOfScope = getNameOfScope(scopeDetermeningObject); // for(IContainer visibleContainer : manager.getVisibleContainers(descr, descriptionIndex)) { // for(EClass aClass : eClasses) for (IEObjectDescription objDesc : new NameInScopeFilter( prefixMatch, getExportedObjects(descr, descriptionIndex), // visibleContainer.getExportedObjects(), fqn, nameOfScope, eClasses)) targets.add(objDesc); } else { // This is lookup from the main resource perspective QualifiedName nameOfScope = getNameOfScope(scopeDetermeningObject); for (IEObjectDescription objDesc : new NameInScopeFilter( prefixMatch, // prefixMatch ? exportedPerLastSegment.values() : exportedPerLastSegment.get(fqn.getLastSegment()), // fqn, nameOfScope, eClasses)) targets.add(objDesc); } if (tracer.isTracing()) { for (IEObjectDescription d : targets) tracer.trace(" : ", converter.toString(d.getName()), " in: ", d.getEObjectURI().path()); } return searchPathAdjusted(targets); }
/* * 付款凭证: 客户+保证金充抵+租金 */ @Override public void createVoucherCautionMoney( ContractInfo contractInfo, JSONArray jsonArray, BigDecimal interest, BigDecimal cautionMoney) throws Exception { /** 第一步:建立基本凭证体集合和公用字段字段-开始 */ List<IntereasVoucherHead> headObjList = new ArrayList<IntereasVoucherHead>(); // 凭证头集合 List<IntereasVoucherEntries> bodyList = Lists.newArrayList(); // 凭证体集合 String currentDate = DateUtil.getSystemDate(); // 当前时间 User currentUser = SecurityUtil.getPrincipal(); // 当前登录人 InterOrgCode interOrgCode = this.baseService.findEntityByID(InterOrgCode.class, "inter_orgcode_id_1"); // 所属公司 DictionaryData voucherType = this.baseService.findEntityByID(DictionaryData.class, "voucher_type_1"); // 记账凭证 // //凭证字 DictionaryData currencyNumber = this.baseService.findEntityByID(DictionaryData.class, "currency_type1"); // 人民币 Integer DR = 1; // 借 Integer CR = -1; // 贷 /** 公用字段-结束 */ /** * ************************************ 分割线-以上不动 * ********************************************************** */ /** 本凭证-公用字段-开始 */ String workFlowName = "期末保证金抵扣流程"; // 流程名称 // BigDecimal originalAmount = finstartdate.getStartMoney(); //原币金额 /** 本凭证-公用字段-结束 */ // 抵扣的每期租金 for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObj = jsonArray.getJSONObject(i); BigDecimal rent = new BigDecimal(jsonObj.getDouble("rent")); String planlist = jsonObj.optString("planlist"); if (rent.compareTo(BigDecimal.ZERO) != 0) { /** 第一步:建立凭证体 */ /** 借银行存款 */ /** * ************************************ 凭证体1-分割线-开始 * ******************************************************* */ // 其他应付款-保证金 VoucherassStactsConfig config_01 = this.baseService.findEntityByID(VoucherassStactsConfig.class, "228"); // 凭证配置表 // :其他应付款-保证金 String voucherAbstract = contractInfo.getCustId().getCustName() + "保证金冲抵第" + planlist + "期租金"; // 摘要 // 建立辅助账 List<IntereasVoucherasStacts> stactsList_01 = voucherService.generateVoucherassStacts( contractInfo.getCustId(), null, config_01); // 辅助账集合 /** 1 :建立凭证体1-开始 */ IntereasVoucherEntries body_01 = new IntereasVoucherEntries(); /** * 凭证体参数构建示例: 参数1:dictionaryData 币别数据字段对象 取:数据字典 人民币 currency_type1 || 美元 currency_type2 * 参数2:num_entrySeq 凭证体分录行号 (德银暂时不传入该参数) 参数3:accountNumber 科目编码 ,已封装成对象 参数4:originalAmount * 原币金额 参数5:voucherAbstract 摘要 参数6:entryDC 借贷方向 (1 借方-1 贷方) 参数7:headObj 该凭证体对应的凭证头完整的实体对象信息 */ body_01.setAccountNumber(config_01); // 这个科目 body_01.setOriginalAmount(rent); // 原币金额 body_01.setEntryDC(DR); // 借贷方向 (DR(1) 借方- CR(1) 贷方) body_01.setVoucherAbstract(voucherAbstract); // 摘要 body_01.setCurrencyNumber(currencyNumber); // 币别数据字段对象 body_01.setIntereasVoucherasStactsInAction(stactsList_01); // 保存辅助账 /** 建立凭证体1-结束 */ bodyList.add(body_01); /** * ************************************ 凭证体1-分割线-结束 * ******************************************************* */ /** 第一步:建立凭证体 */ /** 长期应收款-应收融资租赁款-首付款-客户 */ /** * ************************************ 凭证体2-分割线-开始 * ******************************************************* */ // 其他应收款-本金进项税额 VoucherassStactsConfig config_02 = this.baseService.findEntityByID(VoucherassStactsConfig.class, "225"); // 凭证配置表 // 建立辅助账 List<IntereasVoucherasStacts> stactsList_02 = voucherService.generateVoucherassStacts( contractInfo.getCustId(), null, config_02); // 辅助账集合 // 税金 // BigDecimal texEquipAmount = originalAmount.multiply(new BigDecimal(0.17)).setScale(2); // //金额乘以0.17 /** 1 :建立凭证体1-开始 */ IntereasVoucherEntries body_02 = new IntereasVoucherEntries(); /** * 凭证体参数构建示例: 参数1:dictionaryData 币别数据字段对象 取:数据字典 人民币 currency_type1 || 美元 currency_type2 * 参数2:num_entrySeq 凭证体分录行号 (德银暂时不传入该参数) 参数3:accountNumber 科目编码 ,已封装成对象 参数4:originalAmount * 原币金额 参数5:voucherAbstract 摘要 参数6:entryDC 借贷方向 (1 借方-1 贷方) 参数7:headObj 该凭证体对应的凭证头完整的实体对象信息 */ body_02.setAccountNumber(config_02); // 这个科目 body_02.setOriginalAmount(rent); // 原币金额 body_02.setEntryDC(CR); // 借贷方向 (DR(1) 借方- CR(1) 贷方) body_02.setVoucherAbstract(voucherAbstract); // 摘要 body_02.setCurrencyNumber(currencyNumber); // 币别数据字段对象 body_02.setIntereasVoucherasStactsInAction(stactsList_02); // 保存辅助账 /** 建立凭证体1-结束 */ bodyList.add(body_02); } } // //抵扣的每期租金 // for(int i=0;i<jsonArray.length();i++){ // JSONObject jsonObj = jsonArray.getJSONObject(i); // BigDecimal rent=new BigDecimal(jsonObj.getDouble("rent")); // String planlist=jsonObj.optString("planlist"); // if(rent.compareTo(BigDecimal.ZERO)!=0){ // String // voucherAbstractrent="保证金抵充"+contractInfo.getContractNumber()+"-"+contractInfo.getCustId().getCustName()+"第"+planlist+"租金";//摘要 // /** 第一步:建立凭证体 */ // /** 预收账款-客户 */ // /************************************** 凭证体3-分割线-开始 // ********************************************************/ // // 预收账款 // VoucherassStactsConfig config_03 = // this.baseService.findEntityByID(VoucherassStactsConfig.class, "225"); // 凭证配置表 // // 建立辅助账 // List<IntereasVoucherasStacts> stactsList_03 = // voucherService.generateVoucherassStacts(contractInfo.getCustId(), null, config_02); // 辅助账集合 // /** 1 :建立凭证体1-开始 */ // IntereasVoucherEntries body_03 = new IntereasVoucherEntries(); // /** // * 凭证体参数构建示例: 参数1:dictionaryData 币别数据字段对象 取:数据字典 人民币 currency_type1 || 美元 currency_type2 // 参数2:num_entrySeq // * 凭证体分录行号 (德银暂时不传入该参数) 参数3:accountNumber 科目编码 ,已封装成对象 参数4:originalAmount 原币金额 // 参数5:voucherAbstract 摘要 // * 参数6:entryDC 借贷方向 (1 借方-1 贷方) 参数7:headObj 该凭证体对应的凭证头完整的实体对象信息 // */ // body_03.setAccountNumber(config_03); // 这个科目 // body_03.setOriginalAmount(rent); // 原币金额 // body_03.setEntryDC(DR); // 借贷方向 (DR(1) 借方- CR(1) 贷方) // body_03.setVoucherAbstract(voucherAbstractrent); // 摘要 // body_03.setCurrencyNumber(currencyNumber); // 币别数据字段对象 // body_03.setIntereasVoucherasStactsInAction(stactsList_03); // 保存辅助账 // /** 建立凭证体3-结束 */ // bodyList.add(body_03); // // /** 第一步:建立凭证体 */ // /** 长期应收款-应收融资租赁款-租金-客户 */ // /************************************** 凭证体4-分割线-开始 // ********************************************************/ // // 预收账款 // VoucherassStactsConfig config_04 = // this.baseService.findEntityByID(VoucherassStactsConfig.class, "222"); // 凭证配置表 // // 建立辅助账 // List<IntereasVoucherasStacts> stactsList_04 = // voucherService.generateVoucherassStacts(contractInfo.getCustId(), null, config_02); // 辅助账集合 // /** 1 :建立凭证体1-开始 */ // IntereasVoucherEntries body_04 = new IntereasVoucherEntries(); // /** // * 凭证体参数构建示例: 参数1:dictionaryData 币别数据字段对象 取:数据字典 人民币 currency_type1 || 美元 currency_type2 // 参数2:num_entrySeq // * 凭证体分录行号 (德银暂时不传入该参数) 参数3:accountNumber 科目编码 ,已封装成对象 参数4:originalAmount 原币金额 // 参数5:voucherAbstract 摘要 // * 参数6:entryDC 借贷方向 (1 借方-1 贷方) 参数7:headObj 该凭证体对应的凭证头完整的实体对象信息 // */ // body_04.setAccountNumber(config_04); // 这个科目 // body_04.setOriginalAmount(rent); // 原币金额 // body_04.setEntryDC(CR); // 借贷方向 (DR(1) 借方- CR(1) 贷方) // body_04.setVoucherAbstract(voucherAbstractrent); // 摘要 // body_04.setCurrencyNumber(currencyNumber); // 币别数据字段对象 // body_04.setIntereasVoucherasStactsInAction(stactsList_04); // 保存辅助账 // // /** 建立凭证体1-结束 */ // // bodyList.add(body_04); // } // } /** * ************************************ 凭证体2-分割线-结束 * ******************************************************* */ /** 第一步:建立凭证头 */ /** * ************************************ 凭证头-分割线-开始 * ******************************************************* */ /** * 凭证头构建-开始 参数1:companyNumber 所属公司 取:对应UUID 或 InterOrgCode 中的 orgCode 组织机构代码 注:德银要求不做 * 参数2:bizDate 业务发生日期 取:如果是网银,则取网银到账日期,其他留空.待导出本系统时取当时日期, 例: 收款流程 中取网银到账日期 参数3:bookedDate 财务记账日期 * 取:同业务发生日期 参数4:voucherType 凭证字 取: 汉字 "记账凭证" 参数5:generateDate 凭证发生日期 取: 系统当前时间 参数6:modleName * 业务模块 取:标准当前流程名称(凭证产生的模块流程名称) 例:[收款流程] 参数7:contract_number 业务合同号 取:当前实例业务合同号(存在则比填,不存在则传空) * 例:[德银2013第1号] 参数8: creator 制单人 取:当前业务人员 参数9:memo1 备注 取:存在则填,不存在则传空 */ IntereasVoucherHead headObj = new IntereasVoucherHead(); headObj.setCompanyNumber(interOrgCode); // 参数1:所属公司组织机构代码 headObj.setBizDate(currentDate); // 业务发生日期 headObj.setBookedDate(currentDate); // 财务记账日期 headObj.setVoucherType(voucherType); // 凭证字 headObj.setGenerate_date(currentDate); // 凭证发生日期 headObj.setModleName(workFlowName); // 当前流程名称 headObj.setContract_id(contractInfo); // 业务合同号 【德银2013第1号】 headObj.setCreator(currentUser); // 制单人 headObj.setIntereasVoucherEntriesInAction(bodyList); // 保存凭证体 // 添加到凭证头集合 headObjList.add(headObj); /** 凭证头构建-结束 */ /** * ************************************ 凭证头-分割线-结束 * ******************************************************* */ /** * ************************************ 分割线-以下不动 * ********************************************************** */ /** 第三步:保存凭证 */ voucherService.saveVoucherMain(headObjList); }
/** @author Adrian Cole */ public class CreateServerOptions extends BindToJsonPayload { static class File { private final String path; private final String contents; public File(String path, byte[] contents) { this.path = checkNotNull(path, "path"); this.contents = Base64.encodeBytes(checkNotNull(contents, "contents")); checkArgument( path.getBytes().length < 255, String.format( "maximum length of path is 255 bytes. Path specified %s is %d bytes", path, path.getBytes().length)); checkArgument( contents.length < 10 * 1024, String.format( "maximum size of the file is 10KB. Contents specified is %d bytes", contents.length)); } public String getContents() { return contents; } public String getPath() { return path; } } @SuppressWarnings("unused") private class ServerRequest { final String name; final int imageId; final int flavorId; Map<String, String> metadata; List<File> personality; Integer sharedIpGroupId; Addresses addresses; private ServerRequest(String name, int imageId, int flavorId) { this.name = name; this.imageId = imageId; this.flavorId = flavorId; } } private Map<String, String> metadata = Maps.newHashMap(); private List<File> files = Lists.newArrayList(); private Integer sharedIpGroupId; private String publicIp; @Override public void bindToRequest(HttpRequest request, Map<String, String> postParams) { ServerRequest server = new ServerRequest( checkNotNull(postParams.get("name"), "name parameter not present"), Integer.parseInt( checkNotNull(postParams.get("imageId"), "imageId parameter not present")), Integer.parseInt( checkNotNull(postParams.get("flavorId"), "flavorId parameter not present"))); if (metadata.size() > 0) server.metadata = metadata; if (files.size() > 0) server.personality = files; if (sharedIpGroupId != null) server.sharedIpGroupId = this.sharedIpGroupId; if (publicIp != null) { server.addresses = new Addresses(); server.addresses.getPublicAddresses().add(publicIp); server.addresses.setPrivateAddresses(null); } bindToRequest(request, ImmutableMap.of("server", server)); } /** * You may further customize a cloud server by injecting data into the file system of the cloud * server itself. This is useful, for example, for inserting ssh keys, setting configuration * files, or storing data that you want to retrieve from within the instance itself. It is * intended to provide a minimal amount of launch-time personalization. If significant * customization is required, a custom image should be created. The max size of the file path data * is 255 bytes while the max size of the file contents is 10KB. Note that the file contents * should be encoded as a Base64 string and the 10KB limit refers to the number of bytes in the * decoded data not the number of characters in the encoded data. The maximum number of file * path/content pairs that can be supplied is 5. Any existing files that match the specified file * will be renamed to include the extension bak followed by a time stamp. For example, the file * /etc/passwd will be backed up as /etc/passwd.bak.1246036261.5785. All files will have root and * the root group as owner and group owner, respectively and will allow user and group read access * only (-r--r-----). */ public CreateServerOptions withFile(String path, byte[] contents) { checkState(files.size() < 5, "maximum number of files allowed is 5"); files.add(new File(path, contents)); return this; } /** * A shared IP group is a collection of servers that can share IPs with other members of the * group. Any server in a group can share one or more public IPs with any other server in the * group. With the exception of the first server in a shared IP group, servers must be launched * into shared IP groups. A server may only be a member of one shared IP group. * * <p>Servers in the same shared IP group can share public IPs for various high availability and * load balancing configurations. To launch an HA server, include the optional sharedIpGroupId * element and the server will be launched into that shared IP group. * * <p>Note: sharedIpGroupId is an optional parameter and for optimal performance, should ONLY be * specified when intending to share IPs between servers. * * @see #withSharedIp(String) */ public CreateServerOptions withSharedIpGroup(int id) { checkArgument(id > 0, "id must be positive or zero. was: " + id); this.sharedIpGroupId = id; return this; } /** * Custom cloud server metadata can also be supplied at launch time. This metadata is stored in * the API system where it is retrievable by querying the API for server status. The maximum size * of the metadata key and value is each 255 bytes and the maximum number of key-value pairs that * can be supplied per server is 5. */ public CreateServerOptions withMetadata(Map<String, String> metadata) { checkNotNull(metadata, "metadata"); checkArgument( metadata.size() <= 5, "you cannot have more then 5 metadata values. You specified: " + metadata.size()); for (Entry<String, String> entry : metadata.entrySet()) { checkArgument( entry.getKey().getBytes().length < 255, String.format( "maximum length of metadata key is 255 bytes. Key specified %s is %d bytes", entry.getKey(), entry.getKey().getBytes().length)); checkArgument( entry.getKey().getBytes().length < 255, String.format( "maximum length of metadata value is 255 bytes. Value specified for %s (%s) is %d bytes", entry.getKey(), entry.getValue(), entry.getValue().getBytes().length)); } this.metadata = metadata; return this; } /** * Public IP addresses can be shared across multiple servers for use in various high availability * scenarios. When an IP address is shared to another server, the cloud network restrictions are * modified to allow each server to listen to and respond on that IP address (you may optionally * specify that the target server network configuration be modified). Shared IP addresses can be * used with many standard heartbeat facilities (e.g. keepalived) that monitor for failure and * manage IP failover. * * <p>If you intend to use a shared IP on the server being created and have no need for a separate * public IP address, you may launch the server into a shared IP group and specify an IP address * from that shared IP group to be used as its public IP. You can accomplish this by specifying * the public shared IP address in your request. This is optional and is only valid if * sharedIpGroupId is also supplied. */ public CreateServerOptions withSharedIp(String publicIp) { checkState( sharedIpGroupId != null, "sharedIp is invalid unless a shared ip group is specified."); this.publicIp = checkNotNull(publicIp, "ip"); return this; } public static class Builder { /** @see CreateServerOptions#withFile(String,byte []) */ public static CreateServerOptions withFile(String path, byte[] contents) { CreateServerOptions options = new CreateServerOptions(); return options.withFile(path, contents); } /** @see CreateServerOptions#withSharedIpGroup(int) */ public static CreateServerOptions withSharedIpGroup(int id) { CreateServerOptions options = new CreateServerOptions(); return options.withSharedIpGroup(id); } /** @see CreateServerOptions#withMetadata(Map<String, String>) */ public static CreateServerOptions withMetadata(Map<String, String> metadata) { CreateServerOptions options = new CreateServerOptions(); return options.withMetadata(metadata); } /** @see CreateServerOptions#withSharedIp(String) */ public static CreateServerOptions withSharedIp(String publicIp) { CreateServerOptions options = new CreateServerOptions(); return options.withSharedIp(publicIp); } } }