diff --git a/Client/Program.cs b/Client/Program.cs index f9db896b..da3e3835 100644 --- a/Client/Program.cs +++ b/Client/Program.cs @@ -1,10 +1,12 @@ using System.Drawing; +using System.Drawing.Text; using System.Reflection; using TagsCloudContainer.Configuration; using TagsCloudContainer.PointGenerators; using TagsCloudContainer.TextProviders; using TagsCloudContainer; using Autofac; +using NPOI.SS.Util.CellWalk; namespace Client { @@ -14,42 +16,70 @@ static void Main() { var config = new Config(); - ConfigureSupportedReadingFormats(config); - ConfigureFileSource(config); - ConfigureCloudView(config); - ConfigureColor(config); - ConfigurePathToSave(config); - ConfigureStartPoint(config); - ConfigureFont(config); + ConfigureApp(config) + .OnFail(error => Console.WriteLine($"Ошибка конфигурирования: {error}")) + .Then(Run); + } + private static void Run(Config config) + { var container = DependencyInjection.BuildContainer(config); using var scope = container.BeginLifetimeScope(); - scope.Resolve().DrawPicture(); - Console.WriteLine($"результат сохранен в {config.PicturePath}"); + scope.Resolve().DrawPicture() + .OnFail(error => Console.WriteLine($"Ошибка обработки: {error}")) + .Then(a => Console.WriteLine($"результат сохранен в {config.PicturePath}")); + } + + private static Result ConfigureApp(Config config) + { + return ConfigureSupportedReadingFormats(config).AsResult() + .Then(ConfigureFileSource) + .Then(ConfigureCloudView) + .Then(ConfigureColor) + .Then(ConfigurePathToSave) + .Then(ConfigureStartPoint) + .Then(ConfigureFont); } - private static void ConfigureSupportedReadingFormats(Config config) + private static Config ConfigureSupportedReadingFormats(Config config) { Console.WriteLine("Поддерживаются следующие форматы файлов для чтения:"); var textProviders = FindImplemetations(); foreach (var point in textProviders) Console.WriteLine("\t" + point.Key); config.SupportedReadingFormats = textProviders; + return config; + } + + private static Result ConfigureFont(Config config) + { + Console.WriteLine("Введите размер шрифта"); + if (!int.TryParse(Console.ReadLine(), out var fontSize)) + return Result.Fail("invalid fontSize"); + + Console.WriteLine("Введите название шрифта"); + var fontName = Console.ReadLine(); + if (!CheckFont(fontName)) + return Result.Fail("invalid fontName"); + config.Font = new Font(fontName, fontSize); + return Result.Ok(config); } - private static void ConfigureFont(Config config) + private static bool CheckFont(string fontName) { - config.Font = new Font("arial", 12); + var fontCollection = new InstalledFontCollection(); + return fontCollection.Families.Any( + f => f.Name.Equals(fontName, StringComparison.InvariantCultureIgnoreCase)); } - private static void ConfigurePathToSave(Config config) + private static Config ConfigurePathToSave(Config config) { - Console.WriteLine("Введите полный путь и название файла для сохранения"); - var inp = Console.ReadLine(); + var inp = ReadValue("Введите полный путь и название файла для сохранения"); config.PicturePath = inp.Length == 0 ? "1.bmp" : inp; + return config; } - private static void ConfigureStartPoint(Config config) + private static Result ConfigureStartPoint(Config config) { Console.WriteLine("Введите координаты центра поля для рисования" + "\n При некорректном вводе координаты центра составят ( 1000, 1000)"); @@ -58,14 +88,19 @@ private static void ConfigureStartPoint(Config config) if (int.TryParse(xLine, out var xResult) && int.TryParse(yLine, out var yResult)) config.StartPoint = new Point(xResult, yResult); - config.StartPoint = new Point(1000, 1000); + else + config.StartPoint = new Point(1000, 1000); + return Result.Ok(config); } - private static void ConfigureFileSource(Config config) + private static Result ConfigureFileSource(Config config) { - Console.WriteLine("Введите имя файла источника тэгов"); - var inp = Console.ReadLine(); + var inp = ReadValue("Введите имя файла источника тэгов"); + if ((inp.Length != 0) && + !config.SupportedReadingFormats.TryGetValue(Path.GetExtension(inp), out var textProvider)) + return Result.Fail("wrong file format for text source"); config.FilePath = inp.Length == 0 ? @"TestFile.txt" : inp; + return Result.Ok(config); } private static string GetLabel(RainbowColors color) @@ -76,7 +111,7 @@ private static string GetLabel(RainbowColors color) return attribute.LabelText; } - private static void ConfigureColor(Config config) + private static Config ConfigureColor(Config config) { Console.WriteLine("Выборите цвет из возможных:"); var colors = Enum.GetValues(typeof(RainbowColors)) @@ -86,8 +121,8 @@ private static void ConfigureColor(Config config) foreach (var color in colors) Console.WriteLine("\t" + color.Key); - Console.WriteLine("В случае неправильного ввода - цвет будет выбираться случайным образом"); - var inp = Console.ReadLine().ToLower(); + var inp = ReadValue("В случае неправильного ввода - цвет будет выбираться случайным образом") + .ToLower(); if (colors.TryGetValue(inp, out var colorName)) { config.Color = Color.FromName(colorName.ToString()); @@ -96,9 +131,10 @@ private static void ConfigureColor(Config config) else Console.WriteLine("Цвет будет выбираться случайно"); + return config; } - private static void ConfigureCloudView(Config config) + private static Result ConfigureCloudView(Config config) { Console.WriteLine("Выберите внешний вид облака из возможных:"); var pointGenerators = FindImplemetations(); @@ -107,14 +143,13 @@ private static void ConfigureCloudView(Config config) Console.WriteLine("Введите, соблюдая орфографию"); var pointGenerator = Console.ReadLine().ToLower(); if (pointGenerators.TryGetValue(pointGenerator, out var pointGeneratorName)) - config.PointGenerator = pointGeneratorName; - else { - Console.WriteLine("Такой формы не предусмотрено"); - ConfigureCloudView(config); + config.PointGenerator = pointGeneratorName; + return Result.Ok(config); } + return Result.Fail("Такой формы не предусмотрено"); } - + private static Dictionary FindImplemetations() { var assembly = Assembly.LoadFrom("TagsCloudContainer.dll"); @@ -123,11 +158,11 @@ private static Dictionary FindImplemetations() .Where(t => type.IsAssignableFrom(t) && !t.IsInterface) .ToDictionary(x => x.GetCustomAttribute().LabelText.ToLower(), x => x); } - - private static string? ReadValue(string? argName = null) + + private static string ReadValue(string? argName = null) { Console.Write($"{argName ?? ""}: "); return Console.ReadLine(); } } -} +} \ No newline at end of file diff --git a/TagsCloudContainer.Tests/CloudLayoutShould.cs b/TagsCloudContainer.Tests/CloudLayoutShould.cs index c99dd167..d9c5b69b 100644 --- a/TagsCloudContainer.Tests/CloudLayoutShould.cs +++ b/TagsCloudContainer.Tests/CloudLayoutShould.cs @@ -37,7 +37,7 @@ public void PutNextRectangle_ShouldKeepEnteredSize() { var layout = new CloudLayout(new Point(5, 5), new ArchemedianSpiral()); var enteredSize = new Size(3, 4); - var returnedSize = layout.PutNextRectangle(enteredSize).Size; + var returnedSize = layout.PutNextRectangle(enteredSize).GetValueOrThrow().Size; returnedSize.Should().BeEquivalentTo(enteredSize); } diff --git a/TagsCloudContainer.Tests/RegexParserShould.cs b/TagsCloudContainer.Tests/RegexParserShould.cs new file mode 100644 index 00000000..12e5433b --- /dev/null +++ b/TagsCloudContainer.Tests/RegexParserShould.cs @@ -0,0 +1,39 @@ +using FluentAssertions; +using TagsCloudContainer.StringParsers; + +namespace TagsCloudContainer.Tests; + +[TestFixture] +public class RegexParserShould +{ + private RegexParser _parser; + + [SetUp] + public void Setup() + { + _parser = new RegexParser(); + } + + [Test] + public void ReturnsOnlyWords() + { + var input = "This parser should -+- parse all #words, except any *symbols"; + + var result = _parser.GetWordsFromString(input); + var expected = new [] {"This", "parser", "should", "parse", "all", "words", "except", "any", "symbols"}; + + result.IsSuccess.Should().BeTrue(); + result.GetValueOrThrow().ToList().Select(w => w.Value).Should().BeEquivalentTo(expected); + } + + [Test] + public void ReturnsNoWordsIfEmptyInput() + { + var input = ""; + + var result = _parser.GetWordsFromString(input); + + result.Error.Should().Be("Input cannot be empty"); + } +} + diff --git a/TagsCloudContainer.Tests/TagGeneratorShould.cs b/TagsCloudContainer.Tests/TagGeneratorShould.cs index 3ab47e91..318c4489 100644 --- a/TagsCloudContainer.Tests/TagGeneratorShould.cs +++ b/TagsCloudContainer.Tests/TagGeneratorShould.cs @@ -11,11 +11,12 @@ public class TagGeneratorShould [Test] public void SetRightFontSize() { - var processor = new TextProcessor.TextProcessor( - new TxtTextProvider(@"TextFile1.txt"), new RegexParser(), new ToLowerFilter(), new BoringWordFilter()); - var words = processor.WordFrequencies(); + var words = new Dictionary() + { + {new Word("a"), 3} + }; var generator = new TagGenerator.TagGenerator(new RandomColorProvider(), new System.Drawing.Font("arial", 12)); - var result = generator.GenerateTags(words).First(); + var result = generator.GenerateTags(words).GetValueOrThrow().First(); result.Font.Name.Should().Be("Arial"); result.Font.Size.Should().Be(36); diff --git a/TagsCloudContainer.Tests/TextProcessorShould.cs b/TagsCloudContainer.Tests/TextProcessorShould.cs index 07a5cfa9..7408da7a 100644 --- a/TagsCloudContainer.Tests/TextProcessorShould.cs +++ b/TagsCloudContainer.Tests/TextProcessorShould.cs @@ -13,9 +13,9 @@ public void Process() var result = new TextProcessor.TextProcessor( new TxtTextProvider(@"TextFile1.txt"), new RegexParser(), new ToLowerFilter(), new BoringWordFilter(), new ShortWordFilter()).WordFrequencies(); - result.Count.Should().Be(3); + result.GetValueOrThrow().Count.Should().Be(3); - result.MaxBy(word => word.Value).Value.Should().Be(3); + result.GetValueOrThrow().MaxBy(word => word.Value).Value.Should().Be(3); } } } diff --git a/TagsCloudContainer.Tests/TxtTextProviderShould.cs b/TagsCloudContainer.Tests/TxtTextProviderShould.cs index 461f2818..e5f7829b 100644 --- a/TagsCloudContainer.Tests/TxtTextProviderShould.cs +++ b/TagsCloudContainer.Tests/TxtTextProviderShould.cs @@ -15,9 +15,9 @@ public void Setup() [Test] public void ThrowExceptionIfFileNotFounded() { - Action act = () => _provider.ReadFile(); + var result = _provider.ReadFile(); - act.Should().Throw(); + result.Error.Should().Be("File NotExisted.txt does not exist"); } } } \ No newline at end of file diff --git a/TagsCloudContainer/CloudLayout.cs b/TagsCloudContainer/CloudLayout.cs index bcc26d51..0c21865d 100644 --- a/TagsCloudContainer/CloudLayout.cs +++ b/TagsCloudContainer/CloudLayout.cs @@ -9,6 +9,7 @@ public class CloudLayout public readonly Size Size; private readonly IEnumerable _points; private List Rectangles { get; set; } + private readonly Rectangle _frame; public CloudLayout(Point center, IPointGenerator pointGenerator) @@ -19,6 +20,7 @@ public CloudLayout(Point center, IPointGenerator pointGenerator) Size = CountSize(center); Rectangles = []; _points = pointGenerator.GeneratePoints(Center); + _frame = new Rectangle(0, 0, Size.Width, Size.Height); } public CloudLayout(Size size, IPointGenerator pointGenerator) @@ -27,6 +29,7 @@ public CloudLayout(Size size, IPointGenerator pointGenerator) Center = FindCenter(size); Rectangles = []; _points = pointGenerator.GeneratePoints(Center); + _frame = new Rectangle(0, 0, Size.Width, Size.Height); } @@ -42,7 +45,7 @@ private static Point FindCenter(Size size) return new Point(size.Width / 2, size.Height / 2); } - public Rectangle PutNextRectangle(Size rectangleSize) + public Result PutNextRectangle(Size rectangleSize) { foreach (var point in _points) { @@ -50,10 +53,15 @@ public Rectangle PutNextRectangle(Size rectangleSize) rectangleSize); if (IntersectsWithAnyOther(supposed, Rectangles)) continue; - Rectangles.Add(supposed); - return supposed; + if (_frame.Contains(supposed)) + { + Rectangles.Add(supposed); + return supposed; + } + + return Result.Fail("Вышли за границы рисунка"); } - throw new ArgumentException("Not Enough Points Generated"); + return Result.Fail("Not Enough Points Generated"); } public static bool IntersectsWithAnyOther(Rectangle supposed, List others) diff --git a/TagsCloudContainer/ColorProviders/ColorProvider.cs b/TagsCloudContainer/ColorProviders/ColorProvider.cs index 07b3e61e..1df55747 100644 --- a/TagsCloudContainer/ColorProviders/ColorProvider.cs +++ b/TagsCloudContainer/ColorProviders/ColorProvider.cs @@ -1,13 +1,12 @@ using System.Drawing; -using System.Runtime.CompilerServices; namespace TagsCloudContainer.ColorProviders; public class ColorProvider : IColorProvider { - [CompilerGenerated] private readonly Color _color; + private readonly Color _color; public ColorProvider(Color color) => _color = color; - public Color GetColor() => _color; + public Result GetColor() => _color.AsResult(); } \ No newline at end of file diff --git a/TagsCloudContainer/ColorProviders/IColorProvider.cs b/TagsCloudContainer/ColorProviders/IColorProvider.cs index 682ceaa1..baef5936 100644 --- a/TagsCloudContainer/ColorProviders/IColorProvider.cs +++ b/TagsCloudContainer/ColorProviders/IColorProvider.cs @@ -4,5 +4,5 @@ namespace TagsCloudContainer.ColorProviders; public interface IColorProvider { - Color GetColor(); + Result GetColor(); } \ No newline at end of file diff --git a/TagsCloudContainer/ColorProviders/RandomColorProvider.cs b/TagsCloudContainer/ColorProviders/RandomColorProvider.cs index 2d186faa..32f25d78 100644 --- a/TagsCloudContainer/ColorProviders/RandomColorProvider.cs +++ b/TagsCloudContainer/ColorProviders/RandomColorProvider.cs @@ -4,7 +4,7 @@ namespace TagsCloudContainer.ColorProviders; public class RandomColorProvider : IColorProvider { - public Color GetColor() + public Result GetColor() { return Color.FromArgb(Random.Shared.Next(50, 255), Random.Shared.Next(0, 255), Random.Shared.Next(0, 255), Random.Shared.Next(0, 255)); } diff --git a/TagsCloudContainer/PictureMaker.cs b/TagsCloudContainer/PictureMaker.cs index 1b58c696..34cf7620 100644 --- a/TagsCloudContainer/PictureMaker.cs +++ b/TagsCloudContainer/PictureMaker.cs @@ -8,7 +8,8 @@ namespace TagsCloudContainer; public class PictureMaker { private readonly IPointGenerator _pointGenerator; - private readonly IEnumerable _tags; + private readonly ITagsGenerator _tagGenerator; + private readonly ITextProcessor _textProcessor; private readonly string _fileName; private readonly Point _startPoint; @@ -16,21 +17,25 @@ public PictureMaker(IPointGenerator pointGenerator, ITagsGenerator tagGenerator, ITextProcessor textProcessor, string fileName, Point startPoint) { _pointGenerator = pointGenerator; - _tags = tagGenerator.GenerateTags(textProcessor.WordFrequencies()); + _tagGenerator = tagGenerator; + _textProcessor = textProcessor; _fileName = fileName; _startPoint = startPoint; } - public void DrawPicture() + public Result DrawPicture() { var layout = new CloudLayout(_startPoint, _pointGenerator); using var image = new Bitmap(layout.Size.Width, layout.Size.Height); - foreach (var tag in _tags) - { - var rectangle = layout.PutNextRectangle(tag.Frame); - DrawTag(image, rectangle, tag); - } - image.Save(_fileName); + + return _textProcessor.WordFrequencies() + .Then(wordsDict => _tagGenerator.GenerateTags(wordsDict)) + .ForEach(tag => + { + var rectange = layout.PutNextRectangle(tag.Frame) + .Then(rect => DrawTag(image, rect, tag)) + .Then(_ => image.Save(_fileName)); + }); } private static void DrawTag(Bitmap image, Rectangle rectangle, Tag tag) diff --git a/TagsCloudContainer/Result.cs b/TagsCloudContainer/Result.cs new file mode 100644 index 00000000..da5b56b7 --- /dev/null +++ b/TagsCloudContainer/Result.cs @@ -0,0 +1,134 @@ +namespace TagsCloudContainer; + +public class None +{ + private None() + { + } +} + +public struct Result +{ + public Result(string error, T value = default(T)) + { + Error = error; + Value = value; + } + public static implicit operator Result(T v) + { + return Result.Ok(v); + } + + public string Error { get; } + internal T Value { get; } + public T GetValueOrThrow() + { + if (IsSuccess) return Value; + throw new InvalidOperationException($"No value. Only Error {Error}"); + } + public bool IsSuccess => Error == null; +} + +public static class Result +{ + public static Result AsResult(this T value) + { + return Ok(value); + } + + public static Result Ok(T value) + { + return new Result(null, value); + } + public static Result Ok() + { + return Ok(null); + } + + public static Result Fail(string e) + { + return new Result(e); + } + + public static Result Of(Func f, string error = null) + { + try + { + return Ok(f()); + } + catch (Exception e) + { + return Fail(error ?? e.Message); + } + } + + public static Result OfAction(Action f, string error = null) + { + try + { + f(); + return Ok(); + } + catch (Exception e) + { + return Fail(error ?? e.Message); + } + } +} +public static class ResultExtensions +{ + public static Result Then( + this Result input, + Func continuation) + { + return input.Then(inp => Result.Of(() => continuation(inp))); + } + + public static Result Then( + this Result input, + Action continuation) + { + return input.Then(inp => Result.OfAction(() => continuation(inp))); + } + + public static Result Then( + this Result input, + Func> continuation) + { + return input.IsSuccess + ? continuation(input.Value) + : Result.Fail(input.Error); + } + + public static Result OnFail( + this Result input, + Action handleError) + { + if (!input.IsSuccess) handleError(input.Error); + return input; + } + + public static Result ReplaceError( + this Result input, + Func replaceError) + { + if (input.IsSuccess) return input; + return Result.Fail(replaceError(input.Error)); + } + + public static Result RefineError( + this Result input, + string errorMessage) + { + return input.ReplaceError(err => errorMessage + ". " + err); + } + + public static Result ForEach(this Result> input, Action action) + { + if (!input.IsSuccess) return Result.Fail(input.Error); + foreach (var item in input.Value) + action(item); + return Result.Ok(); + } +} + diff --git a/TagsCloudContainer/StringParsers/IStringParser.cs b/TagsCloudContainer/StringParsers/IStringParser.cs index f85d252c..bf6645d6 100644 --- a/TagsCloudContainer/StringParsers/IStringParser.cs +++ b/TagsCloudContainer/StringParsers/IStringParser.cs @@ -2,6 +2,6 @@ { public interface IStringParser { - IEnumerable GetWordsFromString(string input); + Result> GetWordsFromString(string input); } } diff --git a/TagsCloudContainer/StringParsers/RegexParser.cs b/TagsCloudContainer/StringParsers/RegexParser.cs index 9887a74f..cfa20f22 100644 --- a/TagsCloudContainer/StringParsers/RegexParser.cs +++ b/TagsCloudContainer/StringParsers/RegexParser.cs @@ -5,11 +5,12 @@ namespace TagsCloudContainer.StringParsers public class RegexParser : IStringParser { private readonly Regex _regex = new("\\b(?:\\w|-)+\\b", RegexOptions.Compiled); - public IEnumerable GetWordsFromString(string input) + public Result> GetWordsFromString(string input) { - return _regex.Matches(input) - .Cast() - .Select(w => new Word(w.Value)); + if (string.IsNullOrWhiteSpace(input)) + return Result.Fail>("Input cannot be empty"); + return Result.Ok(_regex.Matches(input) + .Select(w => new Word(w.Value))); } } } diff --git a/TagsCloudContainer/TagGenerator/ITagsGenerator.cs b/TagsCloudContainer/TagGenerator/ITagsGenerator.cs index 421c4f02..049a173b 100644 --- a/TagsCloudContainer/TagGenerator/ITagsGenerator.cs +++ b/TagsCloudContainer/TagGenerator/ITagsGenerator.cs @@ -2,6 +2,6 @@ { public interface ITagsGenerator { - IEnumerable GenerateTags(Dictionary wordsDictionary); + Result> GenerateTags(Dictionary wordsDictionary); } } diff --git a/TagsCloudContainer/TagGenerator/TagGenerator.cs b/TagsCloudContainer/TagGenerator/TagGenerator.cs index dff3a334..fd8978ce 100644 --- a/TagsCloudContainer/TagGenerator/TagGenerator.cs +++ b/TagsCloudContainer/TagGenerator/TagGenerator.cs @@ -17,22 +17,49 @@ public TagGenerator(IColorProvider colorProvider, Font defaultFont ) _defaultFont = defaultFont; } - public IEnumerable GenerateTags(Dictionary wordsDictionary) + public Result> GenerateTags(Dictionary wordsDictionary) { - return wordsDictionary - .Select(kvp => new Tag(kvp.Key, SetFont(_defaultFont, kvp.Value), _colorProvider.GetColor(), - SetFrameSize(kvp.Key, SetFont(_defaultFont, kvp.Value), 1, _graphics))); + var tagsResults = new List>(); + + foreach (var kvp in wordsDictionary) + { + var colorResult = _colorProvider.GetColor(); + if (!colorResult.IsSuccess) + return Result.Fail>(colorResult.Error); + + var fontResult = SetFont(_defaultFont, kvp.Value); + if (!fontResult.IsSuccess) + return Result.Fail>(fontResult.Error); + + var frameSizeResult = SetFrameSize(kvp.Key, fontResult.Value, 1, _graphics); + if (!frameSizeResult.IsSuccess) + return Result.Fail>(frameSizeResult.Error); + + tagsResults.Add(Result.Ok(new Tag(kvp.Key, fontResult.Value, colorResult.Value, frameSizeResult.Value))); + } + return Result.Ok(tagsResults.Select(t => t.Value)); } - private static Size SetFrameSize(Word word, Font font, int frameGap, Graphics graphics) + private static Result SetFrameSize(Word? word, Font? font, int frameGap, Graphics? graphics) { + if (word == null) + return Result.Fail("Word is null"); + if (font == null) + return Result.Fail("Font is null"); + if (frameGap <= 0) + return Result.Fail("Frame gap is lesser than 0"); + if (graphics == null) + return Result.Fail("Graphics is null"); + var rect = graphics.MeasureString(word.Value, font).ToSize(); - return new Size(rect.Width + frameGap, rect.Height + frameGap); + return Result.Ok(new Size(rect.Width + frameGap, rect.Height + frameGap)); } - private static Font SetFont(Font font, int amount) + private static Result SetFont(Font? font, int amount) { - return new Font(font.FontFamily, font.Size * amount); + if (amount <= 0) + return Result.Fail("Amount must be greater than 0"); + return font == null ? Result.Fail("Font is null") : new Font(font.FontFamily, font.Size * amount).AsResult(); } } } diff --git a/TagsCloudContainer/TextProcessor/ITextProcessor.cs b/TagsCloudContainer/TextProcessor/ITextProcessor.cs index b22fb0fd..d227e9fb 100644 --- a/TagsCloudContainer/TextProcessor/ITextProcessor.cs +++ b/TagsCloudContainer/TextProcessor/ITextProcessor.cs @@ -2,6 +2,6 @@ { public interface ITextProcessor { - public Dictionary WordFrequencies(); + public Result> WordFrequencies(); } } diff --git a/TagsCloudContainer/TextProcessor/TextProcessor.cs b/TagsCloudContainer/TextProcessor/TextProcessor.cs index 03f2fe10..773d420c 100644 --- a/TagsCloudContainer/TextProcessor/TextProcessor.cs +++ b/TagsCloudContainer/TextProcessor/TextProcessor.cs @@ -7,11 +7,12 @@ namespace TagsCloudContainer.TextProcessor; public class TextProcessor(ITextProvider provider, IStringParser parser, params IWordFilter[] filters) : ITextProcessor { - public Dictionary WordFrequencies() + public Result> WordFrequencies() { - var words = parser.GetWordsFromString(provider.ReadFile()); - return filters.Aggregate(words, (current, filter) => filter.Process(current)) - .GroupBy(word => word) - .ToDictionary(group => group.Key, group => group.Count()); + return provider.ReadFile() + .Then(text => parser.GetWordsFromString(text)) + .Then(words => filters.Aggregate(words, (current, filter) => filter.Process(current)) + .GroupBy(word => word) + .ToDictionary(group => group.Key, group => group.Count())); } } \ No newline at end of file diff --git a/TagsCloudContainer/TextProviders/DocTextProvider.cs b/TagsCloudContainer/TextProviders/DocTextProvider.cs index cfdd9cc1..3b8744ff 100644 --- a/TagsCloudContainer/TextProviders/DocTextProvider.cs +++ b/TagsCloudContainer/TextProviders/DocTextProvider.cs @@ -12,13 +12,12 @@ public DocTextProvider(string filePath) _filePath = filePath; } - public string ReadFile() + public Result ReadFile() { if (!File.Exists(_filePath)) - throw new FileNotFoundException(); + return new Result($"File not found: {_filePath}"); using var stream = new FileStream(_filePath, FileMode.Open, FileAccess.Read); - var document = new HWPFDocument(stream); - var range = document.GetRange(); - return range.Text; + return Result.Of(() => new HWPFDocument(stream)) + .Then(document=> document.GetRange().Text); } } \ No newline at end of file diff --git a/TagsCloudContainer/TextProviders/DocXTextProvider.cs b/TagsCloudContainer/TextProviders/DocXTextProvider.cs index e4e83b22..4c9881a8 100644 --- a/TagsCloudContainer/TextProviders/DocXTextProvider.cs +++ b/TagsCloudContainer/TextProviders/DocXTextProvider.cs @@ -12,11 +12,11 @@ public DocXTextProvider(string filePath) _filePath = filePath; } - public string ReadFile() + public Result ReadFile() { if (!File.Exists(_filePath)) - throw new FileNotFoundException(); + return Result.Fail($"File {_filePath} does not exist"); using var document = DocX.Load(_filePath); - return document.Text; + return Result.Of(() => document.Text); } } \ No newline at end of file diff --git a/TagsCloudContainer/TextProviders/ITextProvider.cs b/TagsCloudContainer/TextProviders/ITextProvider.cs index cb7a29b5..594caa74 100644 --- a/TagsCloudContainer/TextProviders/ITextProvider.cs +++ b/TagsCloudContainer/TextProviders/ITextProvider.cs @@ -2,5 +2,5 @@ public interface ITextProvider { - public string ReadFile(); + public Result ReadFile(); } \ No newline at end of file diff --git a/TagsCloudContainer/TextProviders/TxtTextProvider.cs b/TagsCloudContainer/TextProviders/TxtTextProvider.cs index 1d774fb6..1f2c2b63 100644 --- a/TagsCloudContainer/TextProviders/TxtTextProvider.cs +++ b/TagsCloudContainer/TextProviders/TxtTextProvider.cs @@ -10,10 +10,10 @@ public TxtTextProvider(string filePath) _filePath = filePath; } - public string ReadFile() + public Result ReadFile() { - if (!File.Exists(_filePath)) - throw new FileNotFoundException(); - return File.ReadAllText(_filePath); + return !File.Exists(_filePath) + ? Result.Fail($"File {_filePath} does not exist") + : Result.Of(()=> File.ReadAllText(_filePath)); } } \ No newline at end of file