下面列出了com.google.common.collect.ImmutableMap#keySet ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* 服务方法信息
* 角色: 服务端
*
* @param httpSender
*/
private void getServiceMethodInfo(HttpSender httpSender) {
ProviderInfo info = new ProviderInfo();
info.setAppkey(ProviderInfoRepository.getAppkey());
List<ServiceMethodInfo> serviceMethods = new ArrayList<ServiceMethodInfo>();
ConcurrentMap<String, ImmutableMap<String, Method>> serviceMethodsMap = ProviderInfoRepository.getAllMethods();
for (Map.Entry<String, ImmutableMap<String, Method>> entry : serviceMethodsMap.entrySet()) {
String serviceName = entry.getKey();
ImmutableMap<String, Method> methods = entry.getValue();
Set<String> methodNames = new HashSet<String>();
for (String methodName : methods.keySet()) {
String returnType = methods.get(methodName).getReturnType().getSimpleName();
methodNames.add(methodName + ":" + returnType);
}
ServiceMethodInfo methodsInfo = new ServiceMethodInfo(serviceName, methodNames);
serviceMethods.add(methodsInfo);
}
info.setServiceMethods(serviceMethods);
httpSender.sendObjectJson(info);
}
/**
* Same as {@link #mapByName(Class, Class)} but allows to ignore some values from {@code
* enum1Type}.
*/
public static <E1 extends Enum<E1>, E2 extends Enum<E2>> ImmutableBiMap<E1, E2> mapByName(
Class<E1> enum1Type, Class<E2> enum2Type, ImmutableSet<E1> ignoreValues) {
ImmutableBiMap.Builder<E1, E2> map = ImmutableBiMap.builder();
ImmutableMap<String, E1> enum1ValuesByName = enumValuesByName(enum1Type, ignoreValues);
ImmutableMap<String, E2> enum2ValuesByName = enumValuesByName(enum2Type, ImmutableSet.of());
if (!enum1ValuesByName.keySet().equals(enum2ValuesByName.keySet())) {
throw new IllegalArgumentException(
String.format(
"Enum %s does not have the same values as enum %s: %s vs %s",
enum1Type.getCanonicalName(),
enum2Type.getCanonicalName(),
enum1ValuesByName.keySet(),
enum2ValuesByName.keySet()));
}
for (String enumName : enum1ValuesByName.keySet()) {
map.put(enum1ValuesByName.get(enumName), enum2ValuesByName.get(enumName));
}
return map.build();
}
@Override
public void finish() throws IOException {
final ImmutableMap<Symbol, Double> scores = this.scores.build();
final ImmutableMap<Symbol, Integer> falsePositives = this.falsePositives.build();
final ImmutableMap<Symbol, Integer> truePositives = this.truePositives.build();
final ImmutableMap<Symbol, Integer> falseNegatives = this.falseNegatives.build();
// see guidelines section 7.3.1.1.3 for aggregating rules:
outputDir.mkdirs();
final double meanScore = scores.isEmpty()?Double.NaN:DoubleMath.mean(scores.values());
Files.asCharSink(new File(outputDir, "linearScore.txt"), Charsets.UTF_8)
.write(Double.toString(meanScore));
for (final Symbol queryId : scores.keySet()) {
final File queryDir = new File(outputDir, queryId.asString());
queryDir.mkdirs();
final File queryScoreFile = new File(queryDir, "score.txt");
// avoid dividing by zero
final double normalizer = Math.max(truePositives.get(queryId) + falseNegatives.get(queryId), 1);
// see guidelines referenced above
// pretends that the corpus is a single document
Files.asCharSink(queryScoreFile, Charsets.UTF_8).write(String
.format(SCORE_PATTERN, truePositives.get(queryId), falsePositives.get(queryId),
falseNegatives.get(queryId), 100 * scores.get(queryId) / normalizer));
}
}
private Set<LinkedHashSet<ThreadInfo>> calculateCycleDeadlockChains(ImmutableMap<Long, ThreadInfo> threadInfoMap, Set<LinkedHashSet<ThreadInfo>> cycles) {
ThreadInfo allThreads[] = threadBean.getThreadInfo(threadBean.getAllThreadIds());
Set<LinkedHashSet<ThreadInfo>> deadlockChain = new HashSet<>();
Set<Long> knownDeadlockedThreads = threadInfoMap.keySet();
for (ThreadInfo threadInfo : allThreads) {
Thread.State state = threadInfo.getThreadState();
if (state == Thread.State.BLOCKED && !knownDeadlockedThreads.contains(threadInfo.getThreadId())) {
for (LinkedHashSet cycle : cycles) {
if (cycle.contains(threadInfoMap.get(Long.valueOf(threadInfo.getLockOwnerId())))) {
LinkedHashSet<ThreadInfo> chain = new LinkedHashSet<>();
for (ThreadInfo node = threadInfo; !chain.contains(node); node = threadInfoMap.get(Long.valueOf(node.getLockOwnerId())))
chain.add(node);
deadlockChain.add(chain);
}
}
}
}
return deadlockChain;
}
/**
* Returns a map from the names of members with invariable hashCodes to the values of those
* hashCodes.
*/
private static ImmutableMap<String, Integer> invariableHashes(
ImmutableMap<String, Member> members, ImmutableSet<String> parameters) {
ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
for (String element : members.keySet()) {
if (!parameters.contains(element)) {
Member member = members.get(element);
AnnotationValue annotationValue = member.method.getDefaultValue();
Optional<Integer> invariableHash = invariableHash(annotationValue);
if (invariableHash.isPresent()) {
builder.put(element, (element.hashCode() * 127) ^ invariableHash.get());
}
}
}
return builder.build();
}
public static ImmutableMap<Path, SourcePath> addMissingInitModules(
ImmutableMap<Path, SourcePath> modules, SourcePath emptyInit) {
Map<Path, SourcePath> initModules = new LinkedHashMap<>();
// Insert missing `__init__.py` modules.
Set<Path> packages = new HashSet<>();
for (Path module : modules.keySet()) {
Path pkg = module;
while ((pkg = pkg.getParent()) != null && !packages.contains(pkg)) {
Path init = pkg.resolve("__init__.py");
if (!modules.containsKey(init)) {
initModules.put(init, emptyInit);
}
packages.add(pkg);
}
}
return ImmutableMap.<Path, SourcePath>builder().putAll(modules).putAll(initModules).build();
}
/** Lowers all given classes to bytecode. */
public static Lowered lowerAll(
ImmutableMap<ClassSymbol, SourceTypeBoundClass> units,
ImmutableList<SourceModuleInfo> modules,
Env<ClassSymbol, BytecodeBoundClass> classpath) {
CompoundEnv<ClassSymbol, TypeBoundClass> env =
CompoundEnv.<ClassSymbol, TypeBoundClass>of(classpath).append(new SimpleEnv<>(units));
ImmutableMap.Builder<String, byte[]> result = ImmutableMap.builder();
Set<ClassSymbol> symbols = new LinkedHashSet<>();
for (ClassSymbol sym : units.keySet()) {
result.put(sym.binaryName(), lower(units.get(sym), env, sym, symbols));
}
if (modules.size() == 1) {
// single module mode: the module-info.class file is at the root
result.put("module-info", lower(getOnlyElement(modules), env, symbols));
} else {
// multi-module mode: the output module-info.class are in a directory corresponding to their
// package
for (SourceModuleInfo module : modules) {
result.put(module.name().replace('.', '/') + "/module-info", lower(module, env, symbols));
}
}
return new Lowered(result.build(), ImmutableSet.copyOf(symbols));
}
private <T> CurrencyParameterSensitivities sensitivityDiscountCurve(
ImmutableCreditRatesProvider provider,
Function<ImmutableCreditRatesProvider, CurrencyAmount> valueFn,
MetaProperty<ImmutableMap<T, CreditDiscountFactors>> metaProperty,
CurrencyAmount valueInit) {
ImmutableMap<T, CreditDiscountFactors> baseCurves = metaProperty.get(provider);
CurrencyParameterSensitivities result = CurrencyParameterSensitivities.empty();
for (T key : baseCurves.keySet()) {
CreditDiscountFactors creditDiscountFactors = baseCurves.get(key);
DiscountFactors discountFactors = creditDiscountFactors.toDiscountFactors();
Curve curve = checkDiscountFactors(discountFactors);
int paramCount = curve.getParameterCount();
double[] sensitivity = new double[paramCount];
for (int i = 0; i < paramCount; i++) {
Curve dscBumped = curve.withParameter(i, curve.getParameter(i) + shift);
Map<T, CreditDiscountFactors> mapBumped = new HashMap<>(baseCurves);
mapBumped.put(key, createCreditDiscountFactors(creditDiscountFactors, dscBumped));
ImmutableCreditRatesProvider providerDscBumped = provider.toBuilder().set(metaProperty, mapBumped).build();
sensitivity[i] = (valueFn.apply(providerDscBumped).getAmount() - valueInit.getAmount()) / shift;
}
result = result.combinedWith(
curve.createParameterSensitivity(valueInit.getCurrency(), DoubleArray.copyOf(sensitivity)));
}
return result;
}
@Test
public void testPrimaryAndSecondary() throws IOException {
int numberOfPrimaryDexes = 10;
int numberOfSecondaryDexes = 10;
int numberOfExtraDexes = 0;
ImmutableMap<String, PreDexedFilesSorter.Result> sortResults =
generatePreDexSorterResults(
numberOfPrimaryDexes, numberOfSecondaryDexes, numberOfExtraDexes);
PreDexedFilesSorter.Result rootResult = sortResults.get(APKModuleGraph.ROOT_APKMODULE_NAME);
for (String store : sortResults.keySet()) {
assertThat(store, is(moduleGraph.getRootAPKModule().getName()));
}
assertThat(rootResult.primaryDexInputs.size(), is(numberOfPrimaryDexes));
assertThat(rootResult.secondaryOutputToInputs.keySet().size(), is(1));
assertThat(rootResult.secondaryOutputToInputs.size(), is(numberOfSecondaryDexes + 1));
}
@Test
public void test_getAll_immutable() {
final ImmutableMap<String, ByteBuffer> values = ImmutableMap.of(
"test.key1", ByteBuffer.wrap("test.value1".getBytes()),
"test.key2", ByteBuffer.wrap("test.value2".getBytes()));
for (final Map.Entry<String, ByteBuffer> value : values.entrySet()) {
connectionAttributes.put(value.getKey(), value.getValue());
}
final Optional<Map<String, ByteBuffer>> returnValues1 = connectionAttributes.getAll();
assertTrue(returnValues1.isPresent());
assertAllEquals(values, returnValues1.get());
final AtomicInteger exceptions = new AtomicInteger(0);
for (final String key : values.keySet()) {
try {
returnValues1.get().get(key).put(0, (byte) 10);
} catch (final ReadOnlyBufferException e) {
exceptions.incrementAndGet();
}
}
final Optional<Map<String, ByteBuffer>> returnValues2 = connectionAttributes.getAll();
assertTrue(returnValues2.isPresent());
assertAllEquals(values, returnValues2.get());
assertEquals(values.size(), exceptions.get());
}
private static ImmutableMultimap<String, Response> systemOutputToResponses(
final Symbol docID, final ImmutableMap<String, SystemOutputStore> systemOutputStores,
final ImmutableCollection<AssessedResponse> assessedResponses,
final CorefAnnotation corefAnnotation) throws IOException {
final ImmutableMultimap.Builder<String, Response> ret = ImmutableMultimap.builder();
final ImmutableMultimap<TRC, Response> typeRoleCASAssessed = Multimaps
.index(Iterables.transform(assessedResponses, AssessedResponseFunctions.response()),
TRC.fromResponse(corefAnnotation));
for (final String systemName : systemOutputStores.keySet()) {
final ImmutableMultimap<TRC, Response> systemTRCs = Multimaps
.index(systemOutputStores.get(systemName).read(docID).arguments().responses(),
TRC.fromResponseSafely(corefAnnotation));
for (final TRC overlap : Sets
.intersection(typeRoleCASAssessed.keySet(), systemTRCs.keySet())) {
ret.putAll(systemName, systemTRCs.get(overlap));
}
}
// final ImmutableSet<String> assessedResponsesIDs =
// FluentIterable.from(assessedResponses).transform(
// AssessedResponse.Response).transform(
// Response.uniqueIdFunction()).toSet();
// for (final String systemOutputStoreName : systemOutputStores.keySet()) {
// final ImmutableSet<Response> responses = ImmutableSet.copyOf(
// systemOutputStores.get(systemOutputStoreName).read(docID).arguments().responses());
// final Set<String> overlapsWithAnnotated =
// Sets.intersection(FluentIterable.from(responses).transform(
// Response.uniqueIdFunction()).toSet(), assessedResponsesIDs);
// for (final Response r : responses) {
// if (overlapsWithAnnotated.contains(r.uniqueIdentifier())) {
// ret.put(systemOutputStoreName, r);
// }
// }
// }
return ret.build();
}
private static Iterable<TargetCpuType> getFilteredPlatforms(
ImmutableMap<TargetCpuType, ?> nativePlatforms, ImmutableSet<TargetCpuType> cpuFilters) {
// TODO(agallagher): We currently treat an empty set of filters to mean to allow everything.
// We should fix this by assigning a default list of CPU filters in the descriptions, but
// until we do, if the set of filters is empty, just build for all available platforms.
if (cpuFilters.isEmpty()) {
return nativePlatforms.keySet();
}
Set<TargetCpuType> missing = Sets.difference(cpuFilters, nativePlatforms.keySet());
Preconditions.checkState(
missing.isEmpty(), "Unknown platform types <" + Joiner.on(",").join(missing) + ">");
return cpuFilters;
}
public static void assertMapContains(Map<NodeId, Set<String>> m1,
ImmutableMap<NodeId, Set<String>> m2) {
for (NodeId k : m2.keySet()) {
Assert.assertTrue(m1.containsKey(k));
assertCollectionEquals(m1.get(k), m2.get(k));
}
}
@Test
public void testPrimaryOnly() throws IOException {
int numberOfPrimaryDexes = 10;
int numberOfSecondaryDexes = 0;
int numberOfExtraDexes = 0;
ImmutableMap<String, PreDexedFilesSorter.Result> sortResults =
generatePreDexSorterResults(
numberOfPrimaryDexes, numberOfSecondaryDexes, numberOfExtraDexes);
for (String store : sortResults.keySet()) {
assertThat(store, is(moduleGraph.getRootAPKModule().getName()));
}
assertThat(sortResults.size(), is(1));
}
@Override
public void finish() throws IOException {
final String scorePattern = "TP: %d, FP: %d, FN: %d, Score: %f\n";
// see guidelines section 7.3.1.1.4 for aggregating rules:
// sum over per document contributions, divide by total number of TRFRs in the answer key
// Math.max is to skip division by zero errors.
final double overAllArgScore =
100 * scoreAggregator / Math.max(0.0 + aggregateFNs + aggregateTPs, 1.0);
final String scoreString =
String.format(scorePattern, aggregateTPs, aggregateFPs, aggregateFNs, overAllArgScore);
Files.asCharSink(new File(outputDir, "argScores.txt"), Charsets.UTF_8).write(scoreString);
final File jsonArgScores = new File(outputDir, "argScore.json");
serializer.serializeTo(ArgScoreSummary.of(overAllArgScore,
FMeasureCounts.fromTPFPFN(aggregateTPs, aggregateFPs, aggregateFNs)),
Files.asByteSink(jsonArgScores));
final ImmutableMap<Symbol, Double> scores = this.scores.build();
final ImmutableMap<Symbol, Integer> falsePositives = this.falsePositives.build();
final ImmutableMap<Symbol, Integer> truePositives = this.truePositives.build();
final ImmutableMap<Symbol, Integer> falseNegatives = this.falseNegatives.build();
for (final Symbol docid : scores.keySet()) {
final File docDir = new File(outputDir, docid.asString());
docDir.mkdirs();
final File docScore = new File(docDir, "argScores.txt");
// avoid dividing by zero
final double normalizer = Math.max(truePositives.get(docid) + falseNegatives.get(docid), 1);
// see guidelines referenced above
// pretends that the corpus is a single document
final double normalizedAndScaledArgScore = 100 * scores.get(docid) / normalizer;
Files.asCharSink(docScore, Charsets.UTF_8).write(String
.format(scorePattern, truePositives.get(docid), falsePositives.get(docid),
falseNegatives.get(docid), normalizedAndScaledArgScore));
final File docJsonArgScores = new File(docDir, "argScores.json");
serializer.serializeTo(normalizedAndScaledArgScore, Files.asByteSink(docJsonArgScores));
}
}
/**
* Returns information about which plugins will be deployed, and asynchronously copies the
* corresponding files to the sandbox.
*/
DeployedPluginInfo deployNonBlocking() throws ExecutionException {
if (deployInfoFiles.isEmpty()) {
throw new ExecutionException("No plugin files found. Did the build fail?");
}
List<IntellijPluginDeployInfo> deployInfoList = Lists.newArrayList();
for (File deployInfoFile : deployInfoFiles) {
deployInfoList.addAll(readDeployInfoFromFile(deployInfoFile));
}
ImmutableMap<File, File> filesToDeploy = getFilesToDeploy(executionRoot, deployInfoList);
this.filesToDeploy.putAll(filesToDeploy);
ImmutableSet<File> javaAgentJars =
deployJavaAgents.getValue() ? listJavaAgentFiles(deployInfoList) : ImmutableSet.of();
for (File file : filesToDeploy.keySet()) {
if (!file.exists()) {
throw new ExecutionException(
String.format("Plugin file '%s' not found. Did the build fail?", file.getName()));
}
}
// kick off file copying task asynchronously, so it doesn't block the EDT.
fileCopyingTask =
BlazeExecutor.getInstance()
.submit(
() -> {
for (Map.Entry<File, File> entry : filesToDeploy.entrySet()) {
copyFileToSandbox(entry.getKey(), entry.getValue());
}
return null;
});
return new DeployedPluginInfo(readPluginIds(filesToDeploy.keySet()), javaAgentJars);
}
@Test
public void testOverrideDefaultSdkVersions() throws Exception {
scratch.file("xcode/BUILD",
"xcode_config(",
" name = 'foo',",
" default = ':version512',",
" versions = [':version512', ':version64'],",
")",
"",
"xcode_version(",
" name = 'version512',",
" version = '5.1.2',",
" aliases = ['5', '5.1'],",
" default_ios_sdk_version = '7.1'",
")",
"",
"xcode_version(",
" name = 'version64',",
" version = '6.4',",
" aliases = ['6.0', 'foo', '6'],",
" default_ios_sdk_version = '101',",
" default_watchos_sdk_version = '102',",
" default_tvos_sdk_version = '103',",
" default_macos_sdk_version = '104',",
")");
useConfiguration("--xcode_version=6", "--xcode_version_config=//xcode:foo",
"--ios_sdk_version=15.3", "--watchos_sdk_version=15.4",
"--tvos_sdk_version=15.5", "--macos_sdk_version=15.6");
assertXcodeVersion("6.4");
assertAvailability(XcodeConfigInfo.Availability.UNKNOWN);
ImmutableMap<ApplePlatform, String> platformToVersion =
ImmutableMap.<ApplePlatform, String>builder()
.put(ApplePlatform.IOS_SIMULATOR, "15.3")
.put(ApplePlatform.WATCHOS_SIMULATOR, "15.4")
.put(ApplePlatform.TVOS_SIMULATOR, "15.5")
.put(ApplePlatform.MACOS, "15.6")
.build();
for (ApplePlatform platform : platformToVersion.keySet()) {
DottedVersion version = DottedVersion.fromString(platformToVersion.get(platform));
assertThat(getSdkVersionForPlatform(platform)).isEqualTo(version);
assertThat(getMinimumOsVersionForPlatform(platform)).isEqualTo(version);
}
}
private void refreshHostIpWhiteList() {
if (clusterService.localNode().isMasterNode()) {
MetaData metaData = clusterService.state().getMetaData();
UserMetadata userMetadata = metaData.getUserMetadata();
final UserMetadata.Builder userMetadataBuilder = new UserMetadata.Builder(userMetadata);
ImmutableMap<String, UserProperty> userPropertyMap = userMetadata.getUserProperties();
boolean changed = false;
for (String user : userPropertyMap.keySet()) {
UserProperty userProperty = userPropertyMap.get(user);
Set<String> hostIpWhiteList = userProperty.getHostIpWhiteList();
Set<String> hostnameWhiteList = userProperty.getHostnameWhiteList();
Set<String> newHostIpWhiteList = new HashSet<>();
boolean errorFlag = false;
for (String hostname : hostnameWhiteList) {
try {
InetAddress[] address = InetAddress.getAllByName(hostname);
for (InetAddress addr : address) {
newHostIpWhiteList.add(addr.getHostAddress());
}
} catch (UnknownHostException e) {
logger.error("Unknown host or BNS name: " + hostname);
errorFlag = true;
break;
}
}
newHostIpWhiteList.addAll(userProperty.getIpWhiteList());
if (!errorFlag && !hostIpWhiteList.equals(newHostIpWhiteList)) {
UserProperty.Builder userPropertyBuilder = new UserProperty.Builder(userProperty);
userPropertyBuilder.cleanHostIpWhiteList().addHostIpListToWhiteList(newHostIpWhiteList);
UserProperty newUserProperty = userPropertyBuilder.build();
userMetadataBuilder.addOrChangeUserProperty(user, newUserProperty);
changed = true;
}
}
if (changed) {
clusterService.submitStateUpdateTask("[refresh user hostIpWhiteList]", new ClusterStateUpdateTask() {
@Override
public boolean runOnlyOnMaster() {
return true;
}
@Override
public ClusterState execute(ClusterState currentState) throws Exception {
MetaData.Builder metaDataBuilder = MetaData.builder(currentState.metaData());
metaDataBuilder.putUserMetadata(userMetadataBuilder);
return ClusterState.builder(currentState).metaData(metaDataBuilder).build();
}
@Override
public void onFailure(String source, Throwable t) {
logger.error("unexpected failure during [{}]", t, source);
}
});
}
}
}
private void doTestTypeSimplifier(
AbstractTestProcessor testProcessor, File tmpDir, ImmutableMap<String, String> classToSource)
throws IOException {
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnosticCollector =
new DiagnosticCollector<JavaFileObject>();
StandardJavaFileManager fileManager =
javac.getStandardFileManager(diagnosticCollector, null, null);
StringWriter compilerOut = new StringWriter();
List<String> options = ImmutableList.of(
"-sourcepath", tmpDir.getPath(),
"-d", tmpDir.getPath(),
"-Xlint");
javac.getTask(compilerOut, fileManager, diagnosticCollector, options, null, null);
// This doesn't compile anything but communicates the paths to the JavaFileManager.
ImmutableList.Builder<JavaFileObject> javaFilesBuilder = ImmutableList.builder();
for (String className : classToSource.keySet()) {
JavaFileObject sourceFile = fileManager.getJavaFileForInput(
StandardLocation.SOURCE_PATH, className, Kind.SOURCE);
javaFilesBuilder.add(sourceFile);
}
// Compile the empty source file to trigger the annotation processor.
// (Annotation processors are somewhat misnamed because they run even on classes with no
// annotations.)
JavaCompiler.CompilationTask javacTask = javac.getTask(
compilerOut, fileManager, diagnosticCollector, options,
classToSource.keySet(), javaFilesBuilder.build());
javacTask.setProcessors(ImmutableList.of(testProcessor));
javacTask.call();
List<Diagnostic<? extends JavaFileObject>> diagnostics =
new ArrayList<Diagnostic<? extends JavaFileObject>>(diagnosticCollector.getDiagnostics());
// In the ErrorTestProcessor case, the code being compiled contains a deliberate reference to an
// undefined type, so that we can capture an instance of ErrorType. (Synthesizing one ourselves
// leads to ClassCastException inside javac.) So remove any errors for that from the output, and
// only fail if there were other errors.
for (Iterator<Diagnostic<? extends JavaFileObject>> it = diagnostics.iterator();
it.hasNext(); ) {
Diagnostic<? extends JavaFileObject> diagnostic = it.next();
if (diagnostic.getSource() != null
&& diagnostic.getSource().getName().contains("ExtendsUndefinedType")) {
it.remove();
}
}
// In the ErrorTestProcessor case, compilerOut.toString() will include the error for
// ExtendsUndefinedType, which can safely be ignored, as well as stack traces for any failing
// assertion.
assertEquals(compilerOut.toString() + diagnosticCollector.getDiagnostics(),
ImmutableList.of(), diagnostics);
}
/**
* Validates that non-zero fees are acked (i.e. they are specified and the amount matches).
*
* <p>This is used directly by update operations, i.e. those that otherwise don't have implicit
* costs, and is also used as a helper method to validate if fees are required for operations that
* do have implicit costs, e.g. creates and renews.
*/
public static void validateFeesAckedIfPresent(
final Optional<? extends FeeTransformCommandExtension> feeCommand,
FeesAndCredits feesAndCredits)
throws EppException {
// Check for the case where a fee command extension was required but not provided.
// This only happens when the total fees are non-zero and include custom fees requiring the
// extension.
if (!feeCommand.isPresent()) {
if (!feesAndCredits.getEapCost().isZero()) {
throw new FeesRequiredDuringEarlyAccessProgramException(feesAndCredits.getEapCost());
}
if (feesAndCredits.getTotalCost().isZero() || !feesAndCredits.isFeeExtensionRequired()) {
return;
}
throw new FeesRequiredForNonFreeOperationException(feesAndCredits.getTotalCost());
}
List<Fee> fees = feeCommand.get().getFees();
// The schema guarantees that at least one fee will be present.
checkState(!fees.isEmpty());
BigDecimal total = zeroInCurrency(feeCommand.get().getCurrency());
for (Fee fee : fees) {
if (!fee.hasDefaultAttributes()) {
throw new UnsupportedFeeAttributeException();
}
total = total.add(fee.getCost());
}
for (Credit credit : feeCommand.get().getCredits()) {
if (!credit.hasDefaultAttributes()) {
throw new UnsupportedFeeAttributeException();
}
total = total.add(credit.getCost());
}
Money feeTotal;
try {
feeTotal = Money.of(feeCommand.get().getCurrency(), total);
} catch (ArithmeticException e) {
throw new CurrencyValueScaleException();
}
if (!feeTotal.getCurrencyUnit().equals(feesAndCredits.getCurrency())) {
throw new CurrencyUnitMismatchException();
}
// If more than one fees are required, always validate individual fees.
ImmutableMap<FeeType, Money> expectedFeeMap =
buildFeeMap(feesAndCredits.getFees(), feesAndCredits.getCurrency());
if (expectedFeeMap.size() > 1) {
ImmutableMap<FeeType, Money> providedFeeMap =
buildFeeMap(feeCommand.get().getFees(), feeCommand.get().getCurrency());
for (FeeType type : expectedFeeMap.keySet()) {
if (!providedFeeMap.containsKey(type)) {
throw new FeesMismatchException(type);
}
Money expectedCost = expectedFeeMap.get(type);
if (!providedFeeMap.get(type).isEqual(expectedCost)) {
throw new FeesMismatchException(type, expectedCost);
}
}
}
// Checking if total amount is expected. Extra fees that we are not expecting may be passed in.
// Or if there is only a single fee type expected.
if (!feeTotal.equals(feesAndCredits.getTotalCost())) {
throw new FeesMismatchException(feesAndCredits.getTotalCost());
}
}