Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2010-2024 60East Technologies Inc., All Rights Reserved.
//
// This computer software is owned by 60East Technologies Inc. and is
// protected by U.S. copyright laws and other laws and by international
// treaties. This computer software is furnished by 60East Technologies
// Inc. pursuant to a written license agreement and may be used, copied,
// transmitted, and stored only in accordance with the terms of such
// license agreement and with the inclusion of the above copyright notice.
// This computer software or any other copies thereof may not be provided
// or otherwise made available to any other person.
//
// U.S. Government Restricted Rights. This computer software: (a) was
// developed at private expense and is in all respects the proprietary
// information of 60East Technologies Inc.; (b) was not developed with
// government funds; (c) is a trade secret of 60East Technologies Inc.
// for all purposes of the Freedom of Information Act; and (d) is a
// commercial item and thus, pursuant to Section 12.212 of the Federal
// Acquisition Regulations (FAR) and DFAR Supplement Section 227.7202,
// Government's use, duplication or disclosure of the computer software
// is subject to the restrictions set forth by 60East Technologies Inc..
//
////////////////////////////////////////////////////////////////////////////
package com.crankuptheamps.client;
import com.crankuptheamps.client.fields.CommandField;
import com.crankuptheamps.client.exception.AMPSException;
import java.nio.charset.StandardCharsets;
/**
*
* Command is an encapsulation of a single AMPS command sent by the client.
* Using Command you can build commands to be executed by the client,
* with message processing happening either synchronously via the
* {@link Client} execute() method or asynchronously via the executeAsync()
* methods.
*
* Command is designed to be used as a "builder" enabling AMPS commands
* to be built easily, for example:
*
*
*
* Client client = new Client(...);
* for(Message m : client.execute(new Command("sow").setTopic("topic"))) { ... }
*
*
*
* Notice that the {@link Message} class can represent both command messages
* to AMPS and response messages from AMPS. In contrast, Command represents
* only commands to AMPS, so the class includes only properties that
* are valid on outgoing commands.
*
* @since 4.0.0.0
*/
public class Command {
Message _message;
private boolean _expiration_isSet;
private byte[] _data;
private byte[] _topic;
private CommandId _commandId;
private CommandId _queryId;
private CommandId _subId;
private int _dataLength;
private int _dataOffset;
private int _topicLength;
private int _topicOffset;
private int _ackType;
private int _batchSize = 10;
private int _command;
private int _expiration;
private int _topN = -1;
private long _clientSequenceNumber;
private long _timeout = 0;
private String _bookmark;
private String _correlationId;
private String _dataString;
private String _filter;
private String _options;
private String _orderBy;
private String _sowKey;
private String _sowKeys;
private String _topicString;
/**
* Set the command and reinitialize all other fields to their default
* on-construction values.
*
* @param command
*/
private void init(final int command) {
_command = command;
_bookmark = null;
_commandId = null;
_correlationId = null;
_data = null;
_dataString = null;
_filter = null;
_options = null;
_orderBy = null;
_queryId = null;
_sowKey = null;
_sowKeys = null;
_subId = null;
_topic = null;
_topicString = null;
_ackType = Message.AckType.None;
_batchSize = 10;
_clientSequenceNumber = 0;
_expiration = 0;
_timeout = 0;
_topN = -1;
_expiration_isSet = false;
if ((_command & Message.Command.NoDataCommands) == 0
|| _command == Message.Command.SOWDelete) {
_commandId = com.crankuptheamps.client.CommandId.nextIdentifier();
if (isSow()) {
_queryId = _commandId;
}
if (isSubscribe()) {
_subId = _commandId;
}
}
}
/**
* Returns the SOW key on this command.
*
* @return the sow key
* @since 4.0.0.0
* @deprecated Use getSowKey() instead.
*/
@Deprecated
public String getSOWKey() {
return _sowKey;
}
/**
* Retrieves the State of the World (SOW) key associated with this instance.
*
* @return A string representing the SOW key.
* @since 5.0.0.0
*/
public String getSowKey() {
return _sowKey;
}
/**
* The SowKey for a command is used to publish to a SOW topic with
* explicit keys set by the user rather than AMPS. The SOW key for a
* message is available through the {@link Message#getSowKey} method
* on a message.
*
* @param sowKey the sow key to set
* @return Returns this instance so that various operations can be chained
* together.
* @since 4.3.0.0
* @deprecated Use setSowKey() instead.
*/
@Deprecated
public Command setSOWKey(String sowKey) {
_sowKey = sowKey;
return this;
}
/**
* The SowKey for a command is only used to publish to a SOW topic and if
* the user wants to restrict the command to a set of messages identified
* by key, SowKeys is used instead. The SOW key for a message is available
* through the {@link Message#getSowKey} method on a message.
*
* @param sowKey the sow key to set
* @return Returns this instance so that various operations can be chained
* together.
* @since 5.0.0.0
* @see Command#setSowKeys(String)
* @see Command#getSowKeys()
*/
public Command setSowKey(String sowKey) {
_sowKey = sowKey;
return this;
}
/**
* Returns the SOW keys on this command.
*
* @return the sow key
* @since 5.0.0.0
*/
public String getSowKeys() {
return _sowKeys;
}
/**
* Returns the SOW keys on this command.
*
* @return the sow key
* @since 4.3.0.0
* @deprecated Use getSowKeys() instead
*/
@Deprecated
public String getSOWKeys() {
return _sowKeys;
}
/**
* Sets the SowKeys for this command.
*
* SowKeys are a comma-separated list of unique keys assigned by AMPS to
* SOW messages to be deleted. AMPS uses these ids to locate and remove
* the specified records. The SOW key for a message is available through
* the {@link Message#getSowKey} method on a message. This method specifies
* that the command is only intended to apply to the keys provided.You
* cannot perform bulk updates by including multiple SOW keys in a single
* publish operation. It also works to limit queiries.
*
* @param sowKeys the sow keys to set
* @return Returns this instance so that various operations can be chained
* together.
* @since 5.0.0.0
*/
public Command setSowKeys(String sowKeys) {
_sowKeys = sowKeys;
return this;
}
/**
* The SowKeys for a command are a comma-separated list of the keys that
* AMPS assigns to SOW messages. The SOW key for a message is available
* through the {@link Message#getSowKey} method on a message.
*
* @param sowKeys the sow keys to set
* @return Returns this instance so that various operations can be chained
* together.
* @since 4.0.0.0
* @deprecated Use setSowKeys() instead.
*/
@Deprecated
public Command setSOWKeys(String sowKeys) {
_sowKeys = sowKeys;
return this;
}
/**
* Checks if the current command represents a subscription.
*
* @return {@code true} if this command is a subscription command,
* otherwise {@code false}.
* @since 4.0.0.0
*/
public final boolean isSubscribe() {
return _command == Message.Command.DeltaSubscribe
|| _command == Message.Command.SOWAndDeltaSubscribe
|| _command == Message.Command.SOWAndSubscribe
|| _command == Message.Command.Subscribe;
}
/**
* Checks if the current command represents a State of the World (SOW)
* operation.
*
* @return {@code true} if this command queries a SOW, otherwise
* {@code false}.
* @since 4.0.0.0
*/
public final boolean isSow() {
return _command == Message.Command.SOW
|| _command == Message.Command.SOWAndDeltaSubscribe
|| _command == Message.Command.SOWAndSubscribe;
}
/**
* Checks whether a sequence number is needed for this message based on the
* message command.
*
* @return {@code true} if this command can be associated with a client
* sequence number, {@code false} otherwise.
* @since 4.0.0.0
*/
public boolean needsSequenceNumber() {
return _command == Message.Command.Publish
|| _command == Message.Command.DeltaPublish
|| _command == Message.Command.SOWDelete;
}
/**
* This method converts the input command into bytes using ISO-8859-1 encoding,
* checks its validity, and returns an integer representation of the command.
* If the command is unknown, it raises an IllegalArgumentException.
*
* @param command_ A string value command to be translated.
* @return An integer representation of the command.
* @throws IllegalArgumentException If the provided command cannot be
* recognized.
* @since 4.0.0.0
*/
private int translateCommand(String command_) {
CommandField cf = new CommandField();
cf.set(command_.getBytes(StandardCharsets.ISO_8859_1));
if (!CommandField.encodeCommand(cf.getValue()).equals(command_)) {
throw new IllegalArgumentException("unknown command type " + command_);
}
return cf.getValue();
}
/**
* Create a new Command with no command type or arguments set.
* Provides a starting point for creating 'Command' objects.
*
* @since 4.0.0.0
*/
public Command() {
}
/**
* Create a new `Command` object with the specified command code.
*
* This constructor creates a new `Command` object, initializing it with an
* integer value representing a specific command code. The initialization
* process is handled internally by the constructor.
*
* @param command A {@link Message.Command} value indicating the AMPS command.
* @since 4.0.0.0
*/
public Command(final String command) {
init(translateCommand(command));
}
public Command(final int command) {
init(command);
}
/**
* Resets this 'Command' object with a new Command type and re-initializes all
* other fields altering its purpose. This method allows the reusability of the
* current `Command` object by changing its state to represent a different
* command type.
*
* @param command A {@link Message.Command} value indicating the AMPS command.
* @return This `Command` object with its state reset to the new command type,
* supporting method chaining.
* @since 4.0.0.0
*/
public Command reset(final int command) {
init(command);
return this;
}
/**
* Resets the current 'Command' object with a new command type specified as
* a string value and re-initializes all associated fields. Translates the
* string into a command type using `translateCommand` and alters the object's
* purpose.
*
* @param command A string representing the new command type.
* @return This current 'Command' object with its state reset to the new type,
* allowing method chaining.
*
* @since 4.0.0.0
*/
public Command reset(final String command) {
init(translateCommand(command));
return this;
}
/**
* Gets the automatically generated command ID associated with this command.
*
* @return The commandId, which is automatically generated for some command
* types.
* @since 4.0.0.0
*/
public CommandId getCommandId() {
return _commandId;
}
/**
* Sets a unique command identifier 'CommandId' for this `Command` object.
*
* @param commandId A unique command identifier to be associated with this
* `Command`.
* @return Returns This `Command` object with the specified identifier.
* @since 4.0.0.0
*/
public Command setCommandId(CommandId commandId) {
_commandId = commandId;
return this;
}
/**
* Retrieve the query identifier associated with the 'Command' object. This
* method is used to access the identifier set by the 'setQueryId' method when
* needed. It allows you to read or obtain the QueryId for tracking, monitoring,
* or correlating messages within the messaging system.
*
* @return The query identifier ('CommandId') previously set using the
* 'setQueryId' method, or 'null' if not set.
* @since 4.0.0.0
*/
public CommandId getQueryId() {
return _queryId;
}
/**
* Set a custom QueryId for this Command.
* The QueryId is a unique identifier that you can assign to this command.
* You have the option to set this independently of the Command so customizing
* the QueryId provides flexibility as you can assign QueryIds based on
* application-specific logic. When the QueryId is independent of the Command in
* AMPS, it means you are not bound by the CommandId for assigning QueryIds.
* Instead, you have the freedom to create custom identifiers for queries and
* messages, which can be valuable when you have scenarios when you need to
* correlate responses from different types of queries based on shared
* attributes other than the CommandId.
*
* @param queryId A unique query identifier to be associated with this
* `Command`.
* @return This `Command` object with the specified query identifier.
* @since 4.0.0.0
*/
public Command setQueryId(CommandId queryId) {
_queryId = queryId;
return this;
}
/**
* Retrieves the command type associated with this `Command` object.
*
* @return The command type integer associated with this `Command`.
* @since 4.0.0.0
*/
public int getCommand() {
return _command;
}
/**
* Set the command type for this 'Command' object.
*
* @param command An integer representing the command type to be associated with
* this `Command`.
* @return This `Command` object with the specified command type.
* @since 4.0.0.0
*/
public Command setCommand(int command) {
_command = command;
return this;
}
/**
* Get the topic set on this command.
*
* @return the topic
* @since 4.0.0.0
*/
public String getTopic() {
if (_topic == null)
return _topicString;
if (_message == null)
return new String(_topic, _topicOffset, _topicLength, StandardCharsets.ISO_8859_1);
else
return new String(_topic, _topicOffset, _topicLength, _message.getDecoder().charset());
}
/**
* Set the topic for this command.
*
* @param topic the topic to set
* @return Returns this instance of Command.
* @since 4.0.0.0
*/
public Command setTopic(String topic) {
_topicString = topic;
_topic = null;
return this;
}
/**
* Set the topic for this command from raw bytes, offset, and length.
*
* @param topic The raw bytes to be used for the topic.
* @param offset The offset into topic where the topic data begins
* @param length The length of the topic.
* @return Returns this instance of Command.
* @since 4.0.0.0
*/
public Command setTopic(byte[] topic, int offset, int length) {
_topic = topic;
_topicString = null;
_topicLength = length;
_topicOffset = 0;
return this;
}
/**
* Get the filter for this command.
*
* @return The filter.
* @since 4.0.0.0
*/
public String getFilter() {
return _filter;
}
/**
* Set the filter for this command.
*
* @param filter The filter to set.
* @return Returns this instance of the Command.
* @since 4.0.0.0
*/
public Command setFilter(String filter) {
_filter = filter;
return this;
}
/**
* Get the orderBy clause for this command.
*
* @return The orderBy.
* @since 4.0.0.0
*/
public String getOrderBy() {
return _orderBy;
}
/**
* Set the orderBy clause for this command.
*
* @param orderBy The orderBy to set.
* @return Returns this instance of Command.
* @since 4.0.0.0
*/
public Command setOrderBy(String orderBy) {
_orderBy = orderBy;
return this;
}
/**
* Get the subId set on this command.
*
* @return The subId.
* @since 4.0.0.0
*/
public CommandId getSubId() {
return _subId;
}
/**
* Set the subId for this command.
*
* @param subId The subId to set.
* @return Returns this instance so that various operations can be chained
* together.
* @since 4.0.0.0
*/
public Command setSubId(CommandId subId) {
if (subId != null)
_subId = subId;
return this;
}
/**
* Sets the subId for this command using a string representation.
*
* @param subId The subId to set.
* @return Returns this instance of Command.
* @since 4.0.0.0
*/
public Command setSubId(String subId) {
if (subId != null)
_subId = new CommandId(subId);
return this;
}
/**
* Get the bookmark for this command.
*
* @return The bookmark.
* @since 4.0.0.0
*/
public String getBookmark() {
return _bookmark;
}
/**
* Set the bookmark for this command.
*
* @param bookmark the bookmark to set
* @return The current instance of Command.
* @since 4.0.0.0
*/
public Command setBookmark(String bookmark) {
_bookmark = bookmark;
return this;
}
/**
* Get the options for this command.
*
* @return The options.
* @since 4.0.0.0
*/
public String getOptions() {
return _options;
}
/**
* Set the options for this command. Options are a comma-delimited list.
*
* @param options the options to set
* @return Returns this instance so that various operations can be chained
* together.
* @since 4.0.0.0
*/
public Command setOptions(String options) {
_options = options;
return this;
}
/**
* Get the ackType for this command.
*
* @return The ackType.
* @since 4.0.0.0
*/
public int getAckType() {
return _ackType;
}
/**
* Set the ackType for this command. Different ackTypes are supported
* for each command. See the Command Reference for details.
*
* @param ackType The ackType to set.
* @return The current instance of Command.
* @since 4.0.0.0
*/
public Command setAckType(int ackType) {
if (ackType == Message.AckType.None
|| ackType == Message.AckType.Persisted) {
if (_commandId != null
&& (_command & Message.Command.NoDataCommands) != 0) {
_commandId = null;
}
} else if (_commandId == null) {
_commandId = CommandId.nextIdentifier();
}
_ackType = ackType;
return this;
}
/**
* Adds an additional ackType to the ackTypes already set
* for this Command.
*
* @param ackType the ackType to add
* @return Returns this instance so that various operations can be chained
* together.
* @since 4.0.0.0
*/
public Command addAckType(int ackType) {
_ackType |= ackType;
return this;
}
/**
* Get the data set on this command.
*
* @return The data.
* @since 4.0.0.0
*/
public String getData() {
if (_data == null)
return _dataString;
if (_message == null)
return new String(_data, _dataOffset, _dataLength, StandardCharsets.ISO_8859_1);
else
return new String(_data, _dataOffset, _dataLength, _message.getDecoder().charset());
}
/**
* Set the data for this command.
*
* @param data The data to set.
* @return The current instance of Command.
* @since 4.0.0.0
*/
public Command setData(String data) {
_dataString = data;
_data = null;
return this;
}
/**
* Set the raw data for this command.
*
* @param data The raw bytes to be used for the data.
* @param offset The offset into data where the data begins.
* @param length The length of the data.
* @return The current instance of Command.
* @since 4.0.0.0
*/
public Command setData(byte[] data, int offset, int length) {
_dataString = null;
_data = data;
_dataOffset = offset;
_dataLength = length;
return this;
}
/**
* Set the data for this command.
*
* @param builder a {@link CompositeMessageBuilder} to set self's data from.
* @return The current instance of Command.
*/
public Command setData(CompositeMessageBuilder builder) {
_dataString = null;
_data = builder._bytes;
_dataOffset = 0;
_dataLength = builder._position;
return this;
}
/**
* Gets the timeout set on this command.
*
* @return The timeout value.
* @since 4.0.0.0
*/
public long getTimeout() {
return _timeout;
}
/**
* Set the timeout for this command (in milliseconds). If the client does
* not receive and consume a processed ack within the specified timeout,
* this method throws an exception. Notice that the timeout is monitored
* in the AMPS client, not on the server, and the client receive thread
* receives and consumes the ack from the server.
*
* @param timeout The timeout to set.
* @return The current instance of Command.
* @since 4.0.0.0
*/
public Command setTimeout(long timeout) {
_timeout = timeout;
return this;
}
/**
* Get the topN value for this command.
*
* @return The topN.
* @since 4.0.0.0
*/
public int getTopN() {
return _topN;
}
/**
* Sets the top_n header for this command. This parameter sets a maximum number
* of records returned by a SOW query. This should usually be set as part of the
* command's options string, rather than using this method.
*
* @param topN The topN to set.
* @return The current instance of Command.
* @since 4.0.0.0
*/
public Command setTopN(int topN) {
_topN = topN;
return this;
}
/**
* Get the batchSize set on this command.
*
* @return The batchSize.
* @since 4.0.0.0
*/
public int getBatchSize() {
return _batchSize;
}
/**
* Set the batchSize for this command. This sets the number of records
* returned in a batch during a SOW query.
*
* @param batchSize The batchSize to set.
* @return The current instance of Command.
* @since 4.0.0.0
*/
public Command setBatchSize(int batchSize) {
_batchSize = batchSize;
return this;
}
/**
* Get the expiration set on this command. This method returns 0 if
* no expiration is set. Use {@link Command#hasExpiration() } to check if an
* expiration is set.
*
* @return The expiration
* @since 4.0.0.0
*/
public int getExpiration() {
if (!_expiration_isSet)
return 0;
return _expiration;
}
/**
* Returns true if this command has an expiration set.
*
* @return True if an expiration is set.
* @since 4.0.0.0
*/
public boolean hasExpiration() {
return _expiration_isSet;
}
/**
* Set the expiration for this command. For a publish command to a
* SOW topic or a queue, the expiration sets the amount of time
* to retain the message in the SOW or the queue.
*
* @param expiration The expiration to set.
* @return The current instance of Command.
* @since 4.0.0.0
*/
public Command setExpiration(int expiration) {
_expiration = expiration;
_expiration_isSet = true;
return this;
}
/**
* Clears any expiration value set on self.
*
* @since 4.0.0.0
*/
public void unsetExpiration() {
_expiration_isSet = false;
}
/**
* Binds self to a given client, preparing a message from that client to be
* sent.
*
* @param client_ The client to bind against.
* @return The CommandId for this command, if one is set, or null.
* @throws AMPSException Thrown when preparing the command fails.
* @since 4.0.0.0
*/
protected CommandId prepare(Client client_) throws AMPSException {
if (_message == null) {
_message = client_.allocateMessage();
} else {
_message.reset();
}
_message.setCommand(_command);
if (_commandId != null)
_message.setCommandId(_commandId);
_message.setAckType(_ackType);
if (_bookmark != null)
_message.setBookmark(_bookmark);
if (_data != null)
_message.setData(_data, _dataOffset, _dataLength);
else if (_dataString != null)
_message.setData(_dataString);
if (_filter != null)
_message.setFilter(_filter);
if (_options != null)
_message.setOptions(_options);
if (_orderBy != null)
_message.setOrderBy(_orderBy);
if (_queryId != null)
_message.setQueryId(_queryId);
if (_subId != null)
_message.setSubId(_subId);
if (_topic != null)
_message.setTopic(_topic, _topicOffset, _topicLength);
else if (_topicString != null)
_message.setTopic(_topicString);
if (_expiration_isSet)
_message.setExpiration(_expiration);
if (_sowKey != null)
_message.setSowKey(_sowKey);
if (_sowKeys != null)
_message.setSowKeys(_sowKeys);
if (_batchSize > 1
&& (_command == Message.Command.SOW
|| _command == Message.Command.SOWAndSubscribe
|| _command == Message.Command.SOWAndDeltaSubscribe)) {
_message.setBatchSize(_batchSize);
}
if (_topN != -1)
_message.setTopN(_topN);
if (_correlationId != null)
_message.setCorrelationId(_correlationId);
if (_clientSequenceNumber > 0 && needsSequenceNumber()) {
_message.setSequence(_clientSequenceNumber);
}
return _commandId;
}
/**
* Sets the client sequence number for this command.
*
* @param seqNumber Sequence number for this command.
* @return The current instance of Command.
* @since 4.0.0.0
*/
public Command setClientSequenceNumber(long seqNumber) {
_clientSequenceNumber = seqNumber;
return this;
}
/**
* Get the client sequence number set on this command.
*
* @return The client sequence number generated for this command, or 0 if none
* was generated.
* @since 4.0.0.0
*/
public long getClientSequenceNumber() {
return _clientSequenceNumber;
}
/**
* Sets the correlation Id for this command. The correlation ID
* is an arbitrary string that can be used for whatever purpose the
* application needs. It is not interpreted or used by AMPS. However,
* the correlation ID must only contain characters that are valid base64
* encoded characters.
*
* @param correlationId_ The CorrelationId is a user provided string included in
* the log message for a logon.
* AMPS does not interpret or use this string for any
* other purpose.
* @return The current instance of Command.
* @since 4.0.0.0
*/
public Command setCorrelationId(String correlationId_) {
_correlationId = correlationId_;
return this;
}
/**
* Gets the correlation Id set with this command.
*
* @return The correlation id.
* @since 4.0.0.0
*/
public String getCorrelationId() {
return _correlationId;
}
}