1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package org.graalvm.options; 26 27 import java.util.Arrays; 28 import java.util.Collections; 29 import java.util.Iterator; 30 import java.util.LinkedHashMap; 31 import java.util.List; 32 import java.util.Map; 33 import java.util.NoSuchElementException; 34 35 /** 36 * An interface to a set of {@link OptionDescriptor}s. 37 * 38 * @since 1.0 39 */ 40 public interface OptionDescriptors extends Iterable<OptionDescriptor> { 41 42 /** 43 * An empty set of option descriptors. 44 * 45 * @since 1.0 46 */ 47 OptionDescriptors EMPTY = new OptionDescriptors() { 48 49 public Iterator<OptionDescriptor> iterator() { 50 return Collections.<OptionDescriptor> emptyList().iterator(); 51 } 52 53 public OptionDescriptor get(String key) { 54 return null; 55 } 56 }; 57 58 /** 59 * Gets the {@link OptionDescriptor} matching a given option name or {@code null} if this option 60 * descriptor set doesn't contain a matching option name. 61 * 62 * @since 1.0 63 */ 64 OptionDescriptor get(String optionName); 65 66 /** 67 * Create a union options descriptor out of multiple given descriptors. The operation 68 * descriptors are not checked for duplicate keys. The option descriptors are iterated in 69 * declaration order. 70 * 71 * @since 1.0 72 */ 73 static OptionDescriptors createUnion(OptionDescriptors... descriptors) { 74 if (descriptors.length == 0) { 75 return EMPTY; 76 } else if (descriptors.length == 1) { 77 return descriptors[0]; 78 } else { 79 return new UnionOptionDescriptors(descriptors); 80 } 81 } 82 83 /** 84 * Create an {@link OptionDescriptors} instance from a list. The option descriptors 85 * implementation is backed by a {@link LinkedHashMap} that preserves ordering. 86 * 87 * @since 1.0 88 */ 89 static OptionDescriptors create(List<OptionDescriptor> descriptors) { 90 if (descriptors == null || descriptors.isEmpty()) { 91 return EMPTY; 92 } 93 return new OptionDescriptorsMap(descriptors); 94 } 95 } 96 97 class OptionDescriptorsMap implements OptionDescriptors { 98 99 final Map<String, OptionDescriptor> descriptors = new LinkedHashMap<>(); 100 101 OptionDescriptorsMap(List<OptionDescriptor> descriptorList) { 102 for (OptionDescriptor descriptor : descriptorList) { 103 descriptors.put(descriptor.getName(), descriptor); 104 } 105 } 106 107 @Override 108 public OptionDescriptor get(String optionName) { 109 return descriptors.get(optionName); 110 } 111 112 @Override 113 public Iterator<OptionDescriptor> iterator() { 114 return descriptors.values().iterator(); 115 } 116 117 } 118 119 final class UnionOptionDescriptors implements OptionDescriptors { 120 121 final OptionDescriptors[] descriptorsList; 122 123 UnionOptionDescriptors(OptionDescriptors[] descriptors) { 124 // defensive copy 125 this.descriptorsList = Arrays.copyOf(descriptors, descriptors.length); 126 } 127 128 public Iterator<OptionDescriptor> iterator() { 129 return new Iterator<OptionDescriptor>() { 130 131 Iterator<OptionDescriptor> descriptors = descriptorsList[0].iterator(); 132 int descriptorsIndex = 0; 133 OptionDescriptor next = null; 134 135 public boolean hasNext() { 136 return fetchNext() != null; 137 } 138 139 private OptionDescriptor fetchNext() { 140 if (next != null) { 141 return next; 142 } 143 if (descriptors.hasNext()) { 144 next = descriptors.next(); 145 return next; 146 } else if (descriptorsIndex < descriptorsList.length - 1) { 147 descriptorsIndex++; 148 descriptors = descriptorsList[descriptorsIndex].iterator(); 149 return fetchNext(); 150 } else { 151 return null; 152 } 153 } 154 155 public OptionDescriptor next() { 156 OptionDescriptor fetchedNext = fetchNext(); 157 if (fetchedNext != null) { 158 // consume next 159 this.next = null; 160 return fetchedNext; 161 } else { 162 throw new NoSuchElementException(); 163 } 164 } 165 }; 166 } 167 168 public OptionDescriptor get(String value) { 169 for (OptionDescriptors descriptors : descriptorsList) { 170 OptionDescriptor descriptor = descriptors.get(value); 171 if (descriptor != null) { 172 return descriptor; 173 } 174 } 175 return null; 176 } 177 178 }