Skip to content

Commit

Permalink
Enh 37059890 - Port UniversalExtractor and UniversalUpdater to C++ an…
Browse files Browse the repository at this point in the history
…d .NET

- UniversalExtractor
#nobug80

[git-p4: depot-paths = "//dev/main.net/": change = 111387]
  • Loading branch information
fryp committed Sep 16, 2024
1 parent 1227bfa commit 8754e83
Show file tree
Hide file tree
Showing 3 changed files with 259 additions and 4 deletions.
9 changes: 7 additions & 2 deletions src/Coherence/Config/coherence-pof-config.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0"?>
<!--
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Copyright (c) 2000, 2024, Oracle and/or its affiliates.
Licensed under the Universal Permissive License v 1.0 as shown at
http://oss.oracle.com/licenses/upl.
https://oss.oracle.com/licenses/upl.
-->
<pof-config xmlns="http://schemas.tangosol.com/pof">
<user-type-list>
Expand Down Expand Up @@ -528,6 +528,11 @@
<class-name>Tangosol.Util.Extractor.ConditionalExtractor, Coherence</class-name>
</user-type>

<user-type>
<type-id>192</type-id>
<class-name>Tangosol.Util.Extractor.UniversalExtractor, Coherence</class-name>
</user-type>

<!-- Tangosol.Util.Aggregator namespace (continued) (250-259) -->

<user-type>
Expand Down
219 changes: 219 additions & 0 deletions src/Coherence/Util/Extractor/UniversalExtractor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
/*
* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* https://oss.oracle.com/licenses/upl.
*/
using System;
using System.Diagnostics;
using System.IO;
using System.Text;

using Tangosol.IO.Pof;

namespace Tangosol.Util.Extractor
{
/// <summary>
/// Universal <see cref="IValueExtractor"/> implementation.
/// </summary>
/// <remarks>
/// UniversalExtractor can only run within the Coherence cluster.
/// Refer to the Coherence for Java documentation for more information.
/// </remarks>
/// <author>Cameron Purdy 2002.11.01</author>
/// <author>Gene Gleyzer 2002.11.01</author>
/// <author>Everett Williams 2007.02.01</author>
/// <author>Joe Fialli 2017.11.20</author>
/// <author>Patrick Fry 2024.09.13</author>
/// <since>14.1.2.0.0</since>
public class UniversalExtractor : AbstractExtractor, IValueExtractor, IPortableObject
{
#region Properties

/// <summary>
/// Get the method or property name.
/// </summary>
/// <value>
/// the method or property name.
/// </value>
public virtual string Name
{
get { return m_name; }
}

/// <summary>
/// Gets the array of arguments used to invoke the method.
/// </summary>
/// <value>
/// The array of arguments used to invoke the method.
/// </value>
public virtual Object[] Parameters
{
get { return m_parameters; }
}

#endregion

#region Constructors

/// <summary>
/// Default constructor (necessary for the IPortableObject interface).
/// </summary>
public UniversalExtractor()
{}

/// <summary>
/// Construct a <b>UniversalExtractor</b> based on a member name.
/// </summary>
/// <param name="name">
/// A method or property name.
/// </param>
public UniversalExtractor(string name)
: this(name, null, VALUE)
{
}

/// <summary>
/// Construct a <b>UniversalExtractor</b>.
/// </summary>
/// <param name="name">
/// A method or property name.
/// </param>
/// <param name="parameters">
/// The array of arguments to be used in the method invocation;
/// may be <c>null</c>.
/// </param>
public UniversalExtractor(string name, object[] parameters)
: this(name, parameters, VALUE)
{
}

/// <summary>
/// Construct a <b>UniversalExtractor</b> based on a method name,
/// optional parameters and the entry extraction target.
/// </summary>
/// <param name="name">
/// A method or property name.
/// </param>
/// <param name="parameters">
/// The array of arguments to be used in the method invocation;
/// may be <c>null</c>.
/// </param>
/// <param name="target">
/// One of the <see cref="AbstractExtractor.VALUE"/> or
/// <see cref="AbstractExtractor.KEY"/> values
/// </param>
public UniversalExtractor(string name, object[] parameters, int target)
{
Debug.Assert(name != null);

if (parameters != null && parameters.Length > 0 && !name.EndsWith(METHOD_SUFFIX))
{
throw new ArgumentException("UniversalExtractor constructor: parameter name[value:" + name + "] must end with method suffix \"" + METHOD_SUFFIX + "\" when optional parameters provided");
}
m_name = name;
m_parameters = parameters;
m_target = target;
}

#endregion

#region Object override methods

/// <summary>
/// Provide a human-readable description of this
/// <see cref="IValueExtractor"/> object.
/// </summary>
/// <returns>
/// A human-readable description of this <b>IValueExtractor</b>
/// object.
/// </returns>
public override string ToString()
{
Object[] parameters = m_parameters;
int cParams = parameters == null ? 0 : parameters.Length;

StringBuilder sb = new StringBuilder();
if (m_target == KEY)
{
sb.Append(".Key");
}
sb.Append('.').Append(m_name).Append('(');
for (int i = 0; i < cParams; i++)
{
if (i != 0)
{
sb.Append(", ");
}
sb.Append(parameters[i]);
}
sb.Append(')');

return sb.ToString();
}

#endregion

#region IPortableObject implementation

/// <summary>
/// Restore the contents of a user type instance by reading its state
/// using the specified <see cref="IPofReader"/> object.
/// </summary>
/// <param name="reader">
/// The <b>IPofReader</b> from which to read the object's state.
/// </param>
/// <exception cref="IOException">
/// If an I/O error occurs.
/// </exception>
public virtual void ReadExternal(IPofReader reader)
{
m_name = reader.ReadString(0);
m_parameters = (object[]) reader.ReadArray(1);
m_target = reader.ReadInt32(2);
}

/// <summary>
/// Save the contents of a POF user type instance by writing its
/// state using the specified <see cref="IPofWriter"/> object.
/// </summary>
/// <param name="writer">
/// The <b>IPofWriter</b> to which to write the object's state.
/// </param>
/// <exception cref="IOException">
/// If an I/O error occurs.
/// </exception>
public virtual void WriteExternal(IPofWriter writer)
{
string name = m_name;
if (name == null)
{
throw new InvalidOperationException("UniversalExtractor was constructed without a method name");
}
writer.WriteString(0, name);
writer.WriteArray(1, m_parameters);
writer.WriteInt32(2, m_target);
}

#endregion

#region Data members

/// <summary>
/// The name of the member to invoke.
/// </summary>
protected string m_name;

/// <summary>
/// The parameter array.
/// </summary>
protected Object[] m_parameters;

/// <summary>
/// If m_name ends with this suffix, it represents a method name.
/// </summary>
public static readonly string METHOD_SUFFIX = "()";

#endregion
}
}
35 changes: 33 additions & 2 deletions tests/Coherence.Tests/Util/Extractor/ExtractorTests.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates.
* Copyright (c) 2000, 2024, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
* https://oss.oracle.com/licenses/upl.
*/
using System;
using System.Collections;
Expand Down Expand Up @@ -301,7 +301,38 @@ public void TestReflectionExtractor()
CacheFactory.Shutdown();
}

[Test]
public void TestUniversalExtractor()
{
IValueExtractor extractor = new UniversalExtractor("field");
IValueExtractor extractor1 = new UniversalExtractor("field");
IValueExtractor extractor2 = IdentityExtractor.Instance;
Assert.IsNotNull(extractor);
Assert.AreEqual(extractor.ToString(), extractor1.ToString());

// testing on remote cache
INamedCache cache = CacheFactory.GetCache(CacheName);
cache.Clear();

Address a1 = new Address("street1", "city1", "state1", "zip1");
Address a2 = new Address("street2", "city2", "state2", "zip2");
Address a3 = new Address("street3", "city1", "state3", "zip3");

Hashtable ht = new Hashtable();
ht.Add("universalExtractorKey1", a1);
ht.Add("universalExtractorKey2", a2);
ht.Add("universalExtractorKey3", a3);
cache.InsertAll(ht);

extractor = new UniversalExtractor("city");
IFilter filter = new EqualsFilter(extractor, "city1");
ICollection keys = cache.GetKeys(filter);
Assert.Contains("universalExtractorKey1", (IList) keys);
Assert.Contains("universalExtractorKey3", (IList) keys);
Assert.AreEqual(keys.Count, 2);

CacheFactory.Shutdown();
}

[Test]
public void TestChainedExtractor()
Expand Down

0 comments on commit 8754e83

Please sign in to comment.