nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/CompositeOperation.java
author attila
Thu, 22 Oct 2015 10:43:10 +0200
changeset 33345 ef8c859f7992
parent 33343 23abd10384a5
child 33688 649d5d76f602
permissions -rw-r--r--
8140273: restore use of CompositeOperation.contains where it is needed Reviewed-by: hannesw, sundar
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
33343
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
     1
/*
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
     2
 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
     4
 *
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    10
 *
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    15
 * accompanied this code).
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    16
 *
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    20
 *
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    23
 * questions.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    24
 */
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    25
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    26
/*
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    27
 * This file is available under and governed by the GNU General Public
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    28
 * License version 2 only, as published by the Free Software Foundation.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    29
 * However, the following notice accompanied the original version of this
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    30
 * file, and Oracle licenses the original version of this file under the BSD
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    31
 * license:
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    32
 */
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    33
/*
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    34
   Copyright 2015 Attila Szegedi
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    35
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    36
   Licensed under both the Apache License, Version 2.0 (the "Apache License")
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    37
   and the BSD License (the "BSD License"), with licensee being free to
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    38
   choose either of the two at their discretion.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    39
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    40
   You may not use this file except in compliance with either the Apache
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    41
   License or the BSD License.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    42
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    43
   If you choose to use this file in compliance with the Apache License, the
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    44
   following notice applies to you:
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    45
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    46
       You may obtain a copy of the Apache License at
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    47
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    48
           http://www.apache.org/licenses/LICENSE-2.0
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    49
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    50
       Unless required by applicable law or agreed to in writing, software
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    51
       distributed under the License is distributed on an "AS IS" BASIS,
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    52
       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    53
       implied. See the License for the specific language governing
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    54
       permissions and limitations under the License.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    55
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    56
   If you choose to use this file in compliance with the BSD License, the
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    57
   following notice applies to you:
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    58
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    59
       Redistribution and use in source and binary forms, with or without
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    60
       modification, are permitted provided that the following conditions are
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    61
       met:
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    62
       * Redistributions of source code must retain the above copyright
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    63
         notice, this list of conditions and the following disclaimer.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    64
       * Redistributions in binary form must reproduce the above copyright
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    65
         notice, this list of conditions and the following disclaimer in the
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    66
         documentation and/or other materials provided with the distribution.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    67
       * Neither the name of the copyright holder nor the names of
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    68
         contributors may be used to endorse or promote products derived from
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    69
         this software without specific prior written permission.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    70
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    71
       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    72
       IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    73
       TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    74
       PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    75
       BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    76
       CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    77
       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    78
       BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    79
       WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    80
       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    81
       ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    82
*/
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    83
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    84
package jdk.internal.dynalink;
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    85
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    86
import java.util.Arrays;
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    87
import java.util.Objects;
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    88
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    89
/**
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    90
 * Describes an operation that is composed of at least two other operations. The
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    91
 * component operations are treated as alternatives to each other in order of
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    92
 * preference. The semantics of the composite operation is "first successful".
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    93
 * That is, a composite of {@code GET_PROPERTY|GET_ELEMENT:color} should be
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    94
 * interpreted as <i>get the property named "color" on the object, but if the
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    95
 * property does not exist, then get the collection element named "color"
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    96
 * instead</i>.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    97
 * <p>
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    98
 * Composite operations are helpful in implementation of languages that
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
    99
 * don't distinguish between one or more of the property, method, and element
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   100
 * namespaces, or when expressing operations against objects that can be
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   101
 * considered both ordinary objects and collections, e.g. Java
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   102
 * {@link java.util.Map} objects. A composite operation
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   103
 * {@code GET_PROPERTY|GET_ELEMENT:empty} against a Java map will always match
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   104
 * the {@link java.util.Map#isEmpty()} property, but
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   105
 * {@code GET_ELEMENT|GET_PROPERTY:empty} will actually match a map element with
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   106
 * key {@code "empty"} if the map contains that key, and only fall back to the
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   107
 * {@code isEmpty()} property getter if the map does not contain the key. If
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   108
 * the source language mandates this semantics, it can be easily achieved using
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   109
 * composite operations.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   110
 * <p>
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   111
 * Even if the language itself doesn't distinguish between some of the
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   112
 * namespaces, it can be helpful to map different syntaxes to different
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   113
 * compositions. E.g. the source expression {@code obj.color} could map to
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   114
 * {@code GET_PROPERTY|GET_ELEMENT|GET_METHOD:color}, but a different source
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   115
 * expression that looks like collection element access {@code obj[key]} could
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   116
 * be expressed instead as {@code GET_ELEMENT|GET_PROPERTY|GET_METHOD}.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   117
 * Finally, if the retrieved value is subsequently called, then it makes sense
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   118
 * to bring {@code GET_METHOD} to the front of the list: the getter part of the
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   119
 * source expression {@code obj.color()} should be
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   120
 * {@code GET_METHOD|GET_PROPERTY|GET_ELEMENT:color} and the one for
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   121
 * {@code obj[key]()} should be {@code GET_METHOD|GET_ELEMENT|GET_PROPERTY}.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   122
 * <p>
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   123
 * The elements of a composite operation can not be composites or named
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   124
 * operations, but rather simple operations such are elements of
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   125
 * {@link StandardOperation}. A composite operation itself can serve as the base
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   126
 * operation of a named operation, though; a typical way to construct e.g. the
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   127
 * {@code GET_ELEMENT|GET_PROPERTY:empty} from above would be:
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   128
 * <pre>
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   129
 * Operation getElementOrPropertyEmpty = new NamedOperation(
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   130
 *     new CompositeOperation(
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   131
 *         StandardOperation.GET_ELEMENT,
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   132
 *         StandardOperation.GET_PROPERTY),
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   133
 *     "empty");
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   134
 * </pre>
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   135
 * <p>
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   136
 * Not all compositions make sense. Typically, any combination in any order of
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   137
 * standard getter operations {@code GET_PROPERTY}, {@code GET_ELEMENT}, and
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   138
 * {@code GET_METHOD} make sense, as do combinations of {@code SET_PROPERTY} and
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   139
 * {@code SET_ELEMENT}; other standard operations should not be combined. The
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   140
 * constructor will allow any combination of operations, though.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   141
 */
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   142
public class CompositeOperation implements Operation {
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   143
    private final Operation[] operations;
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   144
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   145
    /**
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   146
     * Constructs a new composite operation.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   147
     * @param operations the components for this composite operation. The passed
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   148
     * array will be cloned.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   149
     * @throws IllegalArgumentException if less than two components are
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   150
     * specified, or any component is itself a {@link CompositeOperation} or a
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   151
     * {@link NamedOperation}.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   152
     * @throws NullPointerException if either the operations array or any of its
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   153
     * elements are {@code null}.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   154
     */
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   155
    public CompositeOperation(final Operation... operations) {
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   156
        Objects.requireNonNull(operations, "operations array is null");
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   157
        if (operations.length < 2) {
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   158
            throw new IllegalArgumentException("Must have at least two operations");
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   159
        }
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   160
        final Operation[] clonedOps = operations.clone();
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   161
        for(int i = 0; i < clonedOps.length; ++i) {
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   162
            final Operation op = clonedOps[i];
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   163
            if (op == null) {
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   164
                throw new NullPointerException("operations[" + i + "] is null");
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   165
            } else if (op instanceof NamedOperation) {
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   166
                throw new IllegalArgumentException("operations[" + i + "] is a NamedOperation");
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   167
            } else if (op instanceof CompositeOperation) {
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   168
                throw new IllegalArgumentException("operations[" + i + "] is a CompositeOperation");
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   169
            }
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   170
        }
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   171
        this.operations = clonedOps;
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   172
    }
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   173
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   174
    /**
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   175
     * Returns the component operations in this composite operation. The
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   176
     * returned array is a copy and changes to it don't have effect on this
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   177
     * object.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   178
     * @return the component operations in this composite operation.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   179
     */
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   180
    public Operation[] getOperations() {
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   181
        return operations.clone();
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   182
    }
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   183
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   184
    /**
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   185
     * Returns the number of component operations in this composite operation.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   186
     * @return the number of component operations in this composite operation.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   187
     */
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   188
    public int getOperationCount() {
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   189
        return operations.length;
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   190
    }
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   191
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   192
    /**
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   193
     * Returns the i-th component operation in this composite operation.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   194
     * @param i the operation index
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   195
     * @return the i-th component operation in this composite operation.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   196
     * @throws IndexOutOfBoundsException if the index is out of range.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   197
     */
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   198
    public Operation getOperation(final int i) {
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   199
        try {
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   200
            return operations[i];
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   201
        } catch (final ArrayIndexOutOfBoundsException e) {
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   202
            throw new IndexOutOfBoundsException(Integer.toString(i));
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   203
        }
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   204
    }
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   205
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   206
    /**
33345
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   207
     * Returns true if this composite operation contains an operation equal to
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   208
     * the specified operation.
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   209
     * @param operation the operation being searched for. Must not be null.
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   210
     * @return true if the if this composite operation contains an operation
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   211
     * equal to the specified operation.
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   212
     */
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   213
    public boolean contains(final Operation operation) {
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   214
        Objects.requireNonNull(operation);
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   215
        for(final Operation component: operations) {
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   216
            if (component.equals(operation)) {
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   217
                return true;
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   218
            }
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   219
        }
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   220
        return false;
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   221
    }
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   222
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   223
    /**
33343
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   224
     * Returns true if the other object is also a composite operation and their
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   225
     * component operations are equal.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   226
     * @param obj the object to compare to
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   227
     * @return true if this object is equal to the other one, false otherwise.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   228
     */
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   229
    @Override
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   230
    public boolean equals(final Object obj) {
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   231
        if (obj == null || obj.getClass() != CompositeOperation.class) {
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   232
            return false;
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   233
        }
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   234
        return Arrays.equals(operations, ((CompositeOperation)obj).operations);
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   235
    }
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   236
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   237
    /**
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   238
     * Returns the hash code of this composite operation. Defined to be equal
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   239
     * to {@code java.util.Arrays.hashCode(operations)}.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   240
     */
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   241
    @Override
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   242
    public int hashCode() {
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   243
        return Arrays.hashCode(operations);
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   244
    };
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   245
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   246
    /**
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   247
     * Returns the string representation of this composite operation. Defined to
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   248
     * be the {@code toString} of its component operations, each separated by
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   249
     * the vertical line character (e.g. {@code "GET_PROPERTY|GET_ELEMENT"}).
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   250
     * @return the string representation of this composite operation.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   251
     */
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   252
    @Override
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   253
    public String toString() {
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   254
        final StringBuilder b = new StringBuilder();
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   255
        b.append(operations[0]);
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   256
        for(int i = 1; i < operations.length; ++i) {
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   257
            b.append('|').append(operations[i]);
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   258
        }
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   259
        return b.toString();
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   260
    }
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   261
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   262
    /**
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   263
     * Returns the components of the passed operation if it is a composite
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   264
     * operation, otherwise returns an array containing the operation itself.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   265
     * This allows for returning an array of component even if it is not known
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   266
     * whether the operation is itself a composite (treating a non-composite
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   267
     * operation as if it were a single-element composite of itself).
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   268
     * @param op the operation whose components are retrieved.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   269
     * @return if the passed operation is a composite operation, returns its
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   270
     * {@link #getOperations()}, otherwise returns the operation itself.
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   271
     */
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   272
    public static Operation[] getOperations(final Operation op) {
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   273
        return op instanceof CompositeOperation
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   274
                ? ((CompositeOperation)op).operations.clone()
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   275
                : new Operation[] { op };
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   276
    }
33345
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   277
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   278
    /**
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   279
     * Returns true if the specified potentially composite operation is a
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   280
     * {@link CompositeOperation} and contains an operation equal to the
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   281
     * specified operation. If {@code composite} is not a
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   282
     * {@link CompositeOperation}, then the two operations are compared for
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   283
     * equality.
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   284
     * @param composite the potentially composite operation. Must not be null.
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   285
     * @param operation the operation being searched for. Must not be null.
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   286
     * @return true if the if the passed operation is a
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   287
     * {@link CompositeOperation} and contains a component operation equal to
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   288
     * the specified operation, or if it is not a {@link CompositeOperation} and
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   289
     * is equal to {@code operation}.
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   290
     */
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   291
    public static boolean contains(final Operation composite, final Operation operation) {
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   292
        if (composite instanceof CompositeOperation) {
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   293
            return ((CompositeOperation)composite).contains(operation);
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   294
        }
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   295
        return composite.equals(Objects.requireNonNull(operation));
ef8c859f7992 8140273: restore use of CompositeOperation.contains where it is needed
attila
parents: 33343
diff changeset
   296
    }
33343
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
diff changeset
   297
}