FixAntenna/NetCore/Validation/FixMessage/FixGroupContainer.cs (197 lines of code) (raw):
// Copyright (c) 2021 EPAM Systems
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Collections.Generic;
using System.Linq;
using Epam.FixAntenna.NetCore.Message;
using Epam.FixAntenna.NetCore.Validation.Utils;
using Epam.FixAntenna.NetCore.Validation.Validators.Condition;
using Epam.FixAntenna.NetCore.Validation.Validators.Condition.Container;
namespace Epam.FixAntenna.NetCore.Validation.FixMessage
{
internal class FixGroupContainer
{
private IDictionary<int, ICondition> _conditionMap;
private IList<Message.FixMessage> _fixMessages;
private ValidationFixMessage _fixMessage;
private ISet<int> _groupConditionalTags;
private int _groupsCount;
private int _groupsCountTag;
private int _groupStartTag;
private readonly FixUtil _util;
private FixGroupContainer(IValidationFixMessage message, FixUtil util)
{
_fixMessage = (ValidationFixMessage)message;
_util = util;
}
public virtual IDictionary<int, ICondition> GetConditionMap()
{
return _conditionMap;
}
public virtual ISet<int> GetGroupConditionalTags()
{
return _groupConditionalTags;
}
public virtual int GetGroupsCountTag()
{
return _groupsCountTag;
}
public virtual IList<Message.FixMessage> GetFixMessages()
{
return _fixMessages;
}
public virtual int GetGroupsCount()
{
return _groupsCount;
}
public virtual int GetGroupStartTag()
{
return _groupStartTag;
}
public virtual FixGroupContainer CreateContainer(ConditionalGroup group)
{
_conditionMap = group.GetConditionMap();
_groupConditionalTags = BuildSetOfGroupConditionalTags(group, _conditionMap);
_groupsCountTag = group.GetRootTag();
return CreateContainer(_groupsCountTag);
}
public virtual FixGroupContainer CreateContainer(int groupsCountTag)
{
_groupsCountTag = groupsCountTag;
var tag = _fixMessage.FullFixMessage.GetTag(groupsCountTag);
var maps = _fixMessage.GetFixFieldByGroupIndt(groupsCountTag);
_fixMessages = new List<Message.FixMessage>();
if (tag == null)
{
foreach (var fixMessageMap in maps)
{
_fixMessages.Add(fixMessageMap.FixMessage);
}
}
else
{
CreateListOfSeparatedGroups(maps);
}
return this;
}
private void CreateListOfSeparatedGroups(IList<FixMessageMap> fixMessageMaps)
{
foreach (var fixMessageMap in fixMessageMaps)
{
var message = fixMessageMap.FixMessage;
CreateSeparateList(_fixMessage, message, _groupsCountTag);
}
}
public virtual FixGroupContainer CreateSeparateList(ValidationFixMessage validationMessage, Message.FixMessage fixMessage,
int groupsCountTag)
{
long groupsCountTemp;
_fixMessage = validationMessage;
_groupsCountTag = groupsCountTag;
if (_fixMessages == null)
{
_fixMessages = new List<Message.FixMessage>();
}
groupsCountTemp = fixMessage.GetTagValueAsLong(groupsCountTag);
_groupsCount += (int)groupsCountTemp;
var fields = new TagValue[fixMessage.Length];
for (var i = 0; i < fixMessage.Length; i++)
{
fields[i] = fixMessage[i];
}
_groupStartTag = _util.GetStartTagForGroup(validationMessage.GetMsgType(), groupsCountTag);
if (groupsCountTemp == 0 && !fixMessage.IsEmpty)
{
_fixMessages.Add(fixMessage);
}
var message = new Message.FixMessage();
for (int index = 0, fixFieldsLength = fields.Length; index < fixFieldsLength; index++)
{
var field = fields[index];
if (field.TagId == groupsCountTag)
{
if (index == fields.Length - 1)
{
var writeUtil = new WriteUtil(this, fixMessage.GetTag(groupsCountTag), groupsCountTemp,
message).Write();
groupsCountTemp = writeUtil.GroupsCountTemp;
}
continue;
}
// TBD: check if we can use "field.equals(fixMessage.GetTag(field.TagId)"
if (field.TagId == _groupStartTag && !message.IsEmpty ||
field.Equals(message.GetTag(field.TagId)))
{
var writeUtil = new WriteUtil(this, fixMessage.GetTag(groupsCountTag), groupsCountTemp, message)
.Write();
groupsCountTemp = writeUtil.GroupsCountTemp;
message = writeUtil.FixMessage;
// added last group to the list.
if (groupsCountTemp - 1 == 0)
{
CreateLastGroup(fixMessage.GetTag(groupsCountTag), groupsCountTemp, fields, index,
fixFieldsLength);
break;
}
}
message.Add(field);
if (index == fields.Length - 1 && !message.IsEmpty)
{
var writeUtil = new WriteUtil(this, fixMessage.GetTag(groupsCountTag), groupsCountTemp, message)
.Write();
groupsCountTemp = writeUtil.GroupsCountTemp;
message = writeUtil.FixMessage;
}
}
return this;
}
private long CreateLastGroup(TagValue tagValue, long groupsCountTemp, TagValue[] fixFields, int index,
int fixFieldsLength)
{
Message.FixMessage fixMessage;
WriteUtil writeUtil;
var lastGroupLength = fixFieldsLength - index;
var lastGroup = new TagValue[lastGroupLength];
Array.Copy(fixFields, index, lastGroup, 0, lastGroupLength);
fixMessage = new Message.FixMessage();
fixMessage.AddAll(lastGroup.ToList());
writeUtil = new WriteUtil(this, tagValue, groupsCountTemp, fixMessage).Write();
groupsCountTemp = writeUtil.GroupsCountTemp;
return groupsCountTemp;
}
private ISet<int> BuildSetOfGroupConditionalTags(ConditionalGroup group, IDictionary<int, ICondition> conditionMap)
{
var groupConditionalTags = new HashSet<int>();
groupConditionalTags.UnionWith(conditionMap.Keys);
groupConditionalTags.Add(group.GetRootTag());
return groupConditionalTags;
}
public static FixGroupContainer CreateFixGroupContainer(IValidationFixMessage message, FixUtil util)
{
return new FixGroupContainer(message, util);
}
private class WriteUtil
{
private readonly FixGroupContainer _container;
private readonly TagValue _tagValue;
public WriteUtil(FixGroupContainer container, TagValue tagValue, long groupsCountTemp, Message.FixMessage fixMessage)
{
_container = container;
_tagValue = tagValue;
GroupsCountTemp = groupsCountTemp;
FixMessage = fixMessage;
}
public long GroupsCountTemp { get; private set; }
public Message.FixMessage FixMessage { get; private set; }
public WriteUtil Write()
{
WriteData(_container._fixMessages, FixMessage, _tagValue);
--GroupsCountTemp;
// create new instance of FixMessage.
FixMessage = new Message.FixMessage();
return this;
}
private void WriteData(IList<Message.FixMessage> messages, Message.FixMessage fixMessage, TagValue tagValue)
{
// added group length
fixMessage.AddTagAtIndex(0, tagValue);
messages.Add(fixMessage);
}
}
}
}