1 /*
 2  * Copyright (c) 2024, 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 
26 package java.lang.reflect.code;
27 
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.LinkedHashMap;
31 import java.util.Map;
32 
33 /**
34  * The quoted form of an operation.
35  * <p>
36  * The quoted form is utilized when the code model of some code is to be obtained rather than obtaining the result of
37  * executing that code. For example passing the of a lambda expression in quoted form rather than the expression being
38  * targeted to a functional interface from which it can be invoked.
39  */
40 public final class Quoted {
41     private final Op op;
42     private final Map<Value, Object> capturedValues;
43 
44     /**
45      * Constructs the quoted form of a given operation.
46      *
47      * @param op the invokable operation.
48      */
49     public Quoted(Op op) {
50         this(op, Map.of());
51     }
52 
53     /**
54      * Constructs the quoted form of a given operation.
55      * <p>
56      * The captured values key set must have the same elements and same encounter order as
57      * operation's captured values, specifically the following expression should evaluate to true:
58      * {@snippet lang=java :
59      * op.capturedValues().equals(new ArrayList<>(capturedValues.keySet()));
60      * }
61      *
62      * @param op             the operation.
63      * @param capturedValues the captured values referred to by the operation
64      * @see Op#capturedValues()
65      */
66     public Quoted(Op op, Map<Value, Object> capturedValues) {
67         // @@@ This check is potentially expensive, remove or keep as assert?
68         // @@@ Or make Quoted an interface, with a module private implementation?
69         assert op.capturedValues().equals(new ArrayList<>(capturedValues.keySet()));
70         this.op = op;
71         this.capturedValues = Collections.unmodifiableMap(new LinkedHashMap<>(capturedValues));
72     }
73 
74     /**
75      * Returns the operation.
76      *
77      * @return the operation.
78      */
79     public Op op() {
80         return op;
81     }
82 
83     /**
84      * Returns the captured values.
85      * <p>
86      * The captured values key set has the same elements and same encounter order as
87      * operation's captured values, specifically the following expression evaluates to true:
88      * {@snippet lang=java :
89      * op().capturedValues().equals(new ArrayList<>(capturedValues().keySet()));
90      * }
91      *
92      * @return the captured values, as an unmodifiable map.
93      */
94     public Map<Value, Object> capturedValues() {
95         return capturedValues;
96     }
97 }