Path: blob/master/src/jdk.dynalink/share/classes/jdk/dynalink/NamedOperation.java
41154 views
/*1* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* This file is available under and governed by the GNU General Public27* License version 2 only, as published by the Free Software Foundation.28* However, the following notice accompanied the original version of this29* file, and Oracle licenses the original version of this file under the BSD30* license:31*/32/*33Copyright 2015 Attila Szegedi3435Redistribution and use in source and binary forms, with or without36modification, are permitted provided that the following conditions are37met:38* Redistributions of source code must retain the above copyright39notice, this list of conditions and the following disclaimer.40* Redistributions in binary form must reproduce the above copyright41notice, this list of conditions and the following disclaimer in the42documentation and/or other materials provided with the distribution.43* Neither the name of the copyright holder nor the names of44contributors may be used to endorse or promote products derived from45this software without specific prior written permission.4647THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS48IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED49TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A50PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER51BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR52CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF53SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR54BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,55WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR56OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF57ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.58*/5960package jdk.dynalink;6162import java.util.Objects;6364/**65* Operation that associates a name with another operation. Typically used with66* operations that normally take a name or an index to bind them to a fixed67* name. E.g.68* <pre>69* new NamedOperation(70* new NamespaceOperation(71* StandardOperation.GET,72* StandardNamespace.PROPERTY),73* "color")74* </pre>75* will be a named operation for getting the property named "color" on the76* object it is applied to, and77* <pre>78* new NamedOperation(79* new NamespaceOperation(80* StandardOperation.GET,81* StandardNamespace.ELEMENT),82* 3)83* </pre>84* will be a named operation for getting the element at index 3 from the collection85* it is applied to ("name" in this context is akin to "address" and encompasses both86* textual names, numeric indices, or any other kinds of addressing that linkers can87* understand). In these cases, the expected signature of the call site for the88* operation will change to no longer include the name parameter. Specifically,89* the documentation for all {@link StandardOperation} members describes how90* they are affected by being incorporated into a named operation.91* <p>While {@code NamedOperation} can be constructed directly, it is often convenient92* to use the {@link Operation#named(Object)} factory method instead, e.g.:93* <pre>94* StandardOperation.GET95* .withNamespace(StandardNamespace.ELEMENT),96* .named(3)97* )98* </pre>99* <p>100* Even though {@code NamedOperation} is most often used with {@link NamespaceOperation} as101* its base, it can have other operations as its base too (except another named operation).102* Specifically, {@link StandardOperation#CALL} as well as {@link StandardOperation#NEW} can103* both be used with {@code NamedOperation} directly. The contract for these operations is such104* that when they are used as named operations, their name is only used for diagnostic messages,105* usually containing the textual representation of the source expression that retrieved the106* callee, e.g. {@code StandardOperation.CALL.named("window.open")}.107* </p>108*/109public final class NamedOperation implements Operation {110private final Operation baseOperation;111private final Object name;112113/**114* Creates a new named operation.115* @param baseOperation the base operation that is associated with a name.116* @param name the name associated with the base operation. Note that the117* name is not necessarily a string, but can be an arbitrary object. As the118* name is used for addressing, it can be an {@link Integer} when meant119* to be used as an index into an array or list etc.120* @throws NullPointerException if either {@code baseOperation} or121* {@code name} is null.122* @throws IllegalArgumentException if {@code baseOperation} is itself a123* {@code NamedOperation}.124*/125public NamedOperation(final Operation baseOperation, final Object name) {126if (baseOperation instanceof NamedOperation) {127throw new IllegalArgumentException("baseOperation is a NamedOperation");128}129this.baseOperation = Objects.requireNonNull(baseOperation, "baseOperation is null");130this.name = Objects.requireNonNull(name, "name is null");131}132133/**134* Returns the base operation of this named operation.135* @return the base operation of this named operation.136*/137public Operation getBaseOperation() {138return baseOperation;139}140141/**142* Returns the name of this named operation.143* @return the name of this named operation.144*/145public Object getName() {146return name;147}148149/**150* Finds or creates a named operation that differs from this one only in the name.151* @param newName the new name to replace the old name with.152* @return a named operation with the changed name.153* @throws NullPointerException if the name is null.154*/155public final NamedOperation changeName(final String newName) {156return new NamedOperation(baseOperation, newName);157}158159/**160* Compares this named operation to another object. Returns true if the161* other object is also a named operation, and both their base operations162* and name are equal.163*/164@Override165public boolean equals(final Object obj) {166if (obj instanceof NamedOperation) {167final NamedOperation other = (NamedOperation)obj;168return baseOperation.equals(other.baseOperation) && name.equals(other.name);169}170return false;171}172173/**174* Returns the hash code of this named operation. It is defined to be equal175* to {@code baseOperation.hashCode() + 31 * name.hashCode()}.176*/177@Override178public int hashCode() {179return baseOperation.hashCode() + 31 * name.hashCode();180}181182/**183* Returns the string representation of this named operation. It is defined184* to be equal to {@code baseOperation.toString() + ":" + name.toString()}.185*/186@Override187public String toString() {188return baseOperation.toString() + ":" + name.toString();189}190191/**192* If the passed operation is a named operation, returns its193* {@link #getBaseOperation()}, otherwise returns the operation as is.194* @param op the operation195* @return the base operation of the passed operation.196*/197public static Operation getBaseOperation(final Operation op) {198return op instanceof NamedOperation ? ((NamedOperation)op).baseOperation : op;199}200201/**202* If the passed operation is a named operation, returns its203* {@link #getName()}, otherwise returns null. Note that a named operation204* object can never have a null name, therefore returning null is indicative205* that the passed operation is not, in fact, a named operation.206* @param op the operation207* @return the name in the passed operation, or null if it is not a named208* operation.209*/210public static Object getName(final Operation op) {211return op instanceof NamedOperation ? ((NamedOperation)op).name : null;212}213}214215216