Skip to content

Commit 8754e83

Browse files
committed
Enh 37059890 - Port UniversalExtractor and UniversalUpdater to C++ and .NET
- UniversalExtractor #nobug80 [git-p4: depot-paths = "//dev/main.net/": change = 111387]
1 parent 1227bfa commit 8754e83

File tree

3 files changed

+259
-4
lines changed

3 files changed

+259
-4
lines changed

src/Coherence/Config/coherence-pof-config.xml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<?xml version="1.0"?>
22
<!--
3-
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
3+
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
44
55
Licensed under the Universal Permissive License v 1.0 as shown at
6-
http://oss.oracle.com/licenses/upl.
6+
https://oss.oracle.com/licenses/upl.
77
-->
88
<pof-config xmlns="http://schemas.tangosol.com/pof">
99
<user-type-list>
@@ -528,6 +528,11 @@
528528
<class-name>Tangosol.Util.Extractor.ConditionalExtractor, Coherence</class-name>
529529
</user-type>
530530

531+
<user-type>
532+
<type-id>192</type-id>
533+
<class-name>Tangosol.Util.Extractor.UniversalExtractor, Coherence</class-name>
534+
</user-type>
535+
531536
<!-- Tangosol.Util.Aggregator namespace (continued) (250-259) -->
532537

533538
<user-type>
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
/*
2+
* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Universal Permissive License v 1.0 as shown at
5+
* https://oss.oracle.com/licenses/upl.
6+
*/
7+
using System;
8+
using System.Diagnostics;
9+
using System.IO;
10+
using System.Text;
11+
12+
using Tangosol.IO.Pof;
13+
14+
namespace Tangosol.Util.Extractor
15+
{
16+
/// <summary>
17+
/// Universal <see cref="IValueExtractor"/> implementation.
18+
/// </summary>
19+
/// <remarks>
20+
/// UniversalExtractor can only run within the Coherence cluster.
21+
/// Refer to the Coherence for Java documentation for more information.
22+
/// </remarks>
23+
/// <author>Cameron Purdy 2002.11.01</author>
24+
/// <author>Gene Gleyzer 2002.11.01</author>
25+
/// <author>Everett Williams 2007.02.01</author>
26+
/// <author>Joe Fialli 2017.11.20</author>
27+
/// <author>Patrick Fry 2024.09.13</author>
28+
/// <since>14.1.2.0.0</since>
29+
public class UniversalExtractor : AbstractExtractor, IValueExtractor, IPortableObject
30+
{
31+
#region Properties
32+
33+
/// <summary>
34+
/// Get the method or property name.
35+
/// </summary>
36+
/// <value>
37+
/// the method or property name.
38+
/// </value>
39+
public virtual string Name
40+
{
41+
get { return m_name; }
42+
}
43+
44+
/// <summary>
45+
/// Gets the array of arguments used to invoke the method.
46+
/// </summary>
47+
/// <value>
48+
/// The array of arguments used to invoke the method.
49+
/// </value>
50+
public virtual Object[] Parameters
51+
{
52+
get { return m_parameters; }
53+
}
54+
55+
#endregion
56+
57+
#region Constructors
58+
59+
/// <summary>
60+
/// Default constructor (necessary for the IPortableObject interface).
61+
/// </summary>
62+
public UniversalExtractor()
63+
{}
64+
65+
/// <summary>
66+
/// Construct a <b>UniversalExtractor</b> based on a member name.
67+
/// </summary>
68+
/// <param name="name">
69+
/// A method or property name.
70+
/// </param>
71+
public UniversalExtractor(string name)
72+
: this(name, null, VALUE)
73+
{
74+
}
75+
76+
/// <summary>
77+
/// Construct a <b>UniversalExtractor</b>.
78+
/// </summary>
79+
/// <param name="name">
80+
/// A method or property name.
81+
/// </param>
82+
/// <param name="parameters">
83+
/// The array of arguments to be used in the method invocation;
84+
/// may be <c>null</c>.
85+
/// </param>
86+
public UniversalExtractor(string name, object[] parameters)
87+
: this(name, parameters, VALUE)
88+
{
89+
}
90+
91+
/// <summary>
92+
/// Construct a <b>UniversalExtractor</b> based on a method name,
93+
/// optional parameters and the entry extraction target.
94+
/// </summary>
95+
/// <param name="name">
96+
/// A method or property name.
97+
/// </param>
98+
/// <param name="parameters">
99+
/// The array of arguments to be used in the method invocation;
100+
/// may be <c>null</c>.
101+
/// </param>
102+
/// <param name="target">
103+
/// One of the <see cref="AbstractExtractor.VALUE"/> or
104+
/// <see cref="AbstractExtractor.KEY"/> values
105+
/// </param>
106+
public UniversalExtractor(string name, object[] parameters, int target)
107+
{
108+
Debug.Assert(name != null);
109+
110+
if (parameters != null && parameters.Length > 0 && !name.EndsWith(METHOD_SUFFIX))
111+
{
112+
throw new ArgumentException("UniversalExtractor constructor: parameter name[value:" + name + "] must end with method suffix \"" + METHOD_SUFFIX + "\" when optional parameters provided");
113+
}
114+
m_name = name;
115+
m_parameters = parameters;
116+
m_target = target;
117+
}
118+
119+
#endregion
120+
121+
#region Object override methods
122+
123+
/// <summary>
124+
/// Provide a human-readable description of this
125+
/// <see cref="IValueExtractor"/> object.
126+
/// </summary>
127+
/// <returns>
128+
/// A human-readable description of this <b>IValueExtractor</b>
129+
/// object.
130+
/// </returns>
131+
public override string ToString()
132+
{
133+
Object[] parameters = m_parameters;
134+
int cParams = parameters == null ? 0 : parameters.Length;
135+
136+
StringBuilder sb = new StringBuilder();
137+
if (m_target == KEY)
138+
{
139+
sb.Append(".Key");
140+
}
141+
sb.Append('.').Append(m_name).Append('(');
142+
for (int i = 0; i < cParams; i++)
143+
{
144+
if (i != 0)
145+
{
146+
sb.Append(", ");
147+
}
148+
sb.Append(parameters[i]);
149+
}
150+
sb.Append(')');
151+
152+
return sb.ToString();
153+
}
154+
155+
#endregion
156+
157+
#region IPortableObject implementation
158+
159+
/// <summary>
160+
/// Restore the contents of a user type instance by reading its state
161+
/// using the specified <see cref="IPofReader"/> object.
162+
/// </summary>
163+
/// <param name="reader">
164+
/// The <b>IPofReader</b> from which to read the object's state.
165+
/// </param>
166+
/// <exception cref="IOException">
167+
/// If an I/O error occurs.
168+
/// </exception>
169+
public virtual void ReadExternal(IPofReader reader)
170+
{
171+
m_name = reader.ReadString(0);
172+
m_parameters = (object[]) reader.ReadArray(1);
173+
m_target = reader.ReadInt32(2);
174+
}
175+
176+
/// <summary>
177+
/// Save the contents of a POF user type instance by writing its
178+
/// state using the specified <see cref="IPofWriter"/> object.
179+
/// </summary>
180+
/// <param name="writer">
181+
/// The <b>IPofWriter</b> to which to write the object's state.
182+
/// </param>
183+
/// <exception cref="IOException">
184+
/// If an I/O error occurs.
185+
/// </exception>
186+
public virtual void WriteExternal(IPofWriter writer)
187+
{
188+
string name = m_name;
189+
if (name == null)
190+
{
191+
throw new InvalidOperationException("UniversalExtractor was constructed without a method name");
192+
}
193+
writer.WriteString(0, name);
194+
writer.WriteArray(1, m_parameters);
195+
writer.WriteInt32(2, m_target);
196+
}
197+
198+
#endregion
199+
200+
#region Data members
201+
202+
/// <summary>
203+
/// The name of the member to invoke.
204+
/// </summary>
205+
protected string m_name;
206+
207+
/// <summary>
208+
/// The parameter array.
209+
/// </summary>
210+
protected Object[] m_parameters;
211+
212+
/// <summary>
213+
/// If m_name ends with this suffix, it represents a method name.
214+
/// </summary>
215+
public static readonly string METHOD_SUFFIX = "()";
216+
217+
#endregion
218+
}
219+
}

tests/Coherence.Tests/Util/Extractor/ExtractorTests.cs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/*
2-
* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
2+
* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
33
*
44
* Licensed under the Universal Permissive License v 1.0 as shown at
5-
* http://oss.oracle.com/licenses/upl.
5+
* https://oss.oracle.com/licenses/upl.
66
*/
77
using System;
88
using System.Collections;
@@ -301,7 +301,38 @@ public void TestReflectionExtractor()
301301
CacheFactory.Shutdown();
302302
}
303303

304+
[Test]
305+
public void TestUniversalExtractor()
306+
{
307+
IValueExtractor extractor = new UniversalExtractor("field");
308+
IValueExtractor extractor1 = new UniversalExtractor("field");
309+
IValueExtractor extractor2 = IdentityExtractor.Instance;
310+
Assert.IsNotNull(extractor);
311+
Assert.AreEqual(extractor.ToString(), extractor1.ToString());
312+
313+
// testing on remote cache
314+
INamedCache cache = CacheFactory.GetCache(CacheName);
315+
cache.Clear();
316+
317+
Address a1 = new Address("street1", "city1", "state1", "zip1");
318+
Address a2 = new Address("street2", "city2", "state2", "zip2");
319+
Address a3 = new Address("street3", "city1", "state3", "zip3");
320+
321+
Hashtable ht = new Hashtable();
322+
ht.Add("universalExtractorKey1", a1);
323+
ht.Add("universalExtractorKey2", a2);
324+
ht.Add("universalExtractorKey3", a3);
325+
cache.InsertAll(ht);
326+
327+
extractor = new UniversalExtractor("city");
328+
IFilter filter = new EqualsFilter(extractor, "city1");
329+
ICollection keys = cache.GetKeys(filter);
330+
Assert.Contains("universalExtractorKey1", (IList) keys);
331+
Assert.Contains("universalExtractorKey3", (IList) keys);
332+
Assert.AreEqual(keys.Count, 2);
304333

334+
CacheFactory.Shutdown();
335+
}
305336

306337
[Test]
307338
public void TestChainedExtractor()

0 commit comments

Comments
 (0)