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.NoSuchElementException;
  31 
  32 /**
  33  * An interface to a set of {@link OptionDescriptor}s.
  34  *
  35  * @since 1.0
  36  */
  37 public interface OptionDescriptors extends Iterable<OptionDescriptor> {
  38 
  39     /**
  40      * An empty set of option descriptors.
  41      *
  42      * @since 1.0
  43      */
  44     OptionDescriptors EMPTY = new OptionDescriptors() {
  45 
  46         public Iterator<OptionDescriptor> iterator() {
  47             return Collections.<OptionDescriptor> emptyList().iterator();
  48         }
  49 
  50         public OptionDescriptor get(String key) {
  51             return null;
  52         }
  53     };
  54 
  55     /**
  56      * Gets the {@link OptionDescriptor} matching a given option name or {@code null} if this option
  57      * descriptor set doesn't contain a matching option name.
  58      *
  59      * @since 1.0
  60      */
  61     OptionDescriptor get(String optionName);
  62 
  63     /**
  64      * Create a union options descriptor out of multiple given descriptors. The operation
  65      * descriptors are not checked for duplicate keys. The option descriptors are iterated in
  66      * declaration order.
  67      *
  68      * @since 1.0
  69      */
  70     static OptionDescriptors createUnion(OptionDescriptors... descriptors) {
  71         if (descriptors.length == 0) {
  72             return EMPTY;
  73         } else if (descriptors.length == 1) {
  74             return descriptors[0];
  75         } else {
  76             return new UnionOptionDescriptors(descriptors);
  77         }
  78     }
  79 }
  80 
  81 final class UnionOptionDescriptors implements OptionDescriptors {
  82 
  83     final OptionDescriptors[] descriptorsList;
  84 
  85     UnionOptionDescriptors(OptionDescriptors[] descriptors) {
  86         // defensive copy
  87         this.descriptorsList = Arrays.copyOf(descriptors, descriptors.length);
  88     }
  89 
  90     public Iterator<OptionDescriptor> iterator() {
  91         return new Iterator<OptionDescriptor>() {
  92 
  93             Iterator<OptionDescriptor> descriptors = descriptorsList[0].iterator();
  94             int descriptorsIndex = 0;
  95             OptionDescriptor next = null;
  96 
  97             public boolean hasNext() {
  98                 return fetchNext() != null;
  99             }
 100 
 101             private OptionDescriptor fetchNext() {
 102                 if (next != null) {
 103                     return next;
 104                 }
 105                 if (descriptors.hasNext()) {
 106                     next = descriptors.next();
 107                     return next;
 108                 } else if (descriptorsIndex < descriptorsList.length - 1) {
 109                     descriptorsIndex++;
 110                     descriptors = descriptorsList[descriptorsIndex].iterator();
 111                     return fetchNext();
 112                 } else {
 113                     return null;
 114                 }
 115             }
 116 
 117             public OptionDescriptor next() {
 118                 OptionDescriptor fetchedNext = fetchNext();
 119                 if (fetchedNext != null) {
 120                     // consume next
 121                     this.next = null;
 122                     return fetchedNext;
 123                 } else {
 124                     throw new NoSuchElementException();
 125                 }
 126             }
 127         };
 128     }
 129 
 130     public OptionDescriptor get(String value) {
 131         for (OptionDescriptors descriptors : descriptorsList) {
 132             OptionDescriptor descriptor = descriptors.get(value);
 133             if (descriptor != null) {
 134                 return descriptor;
 135             }
 136         }
 137         return null;
 138     }
 139 
 140 }