private IDictionary<string, Guid> ImportCategories(BlogMLBlog.CategoryCollection categories,
IEnumerable<BlogMLPost> blogs,
ref List<CategoryTree> newCategoriesTreeList,
ref List<Category> newCategoriesList,
bool ReuseExistingCategories,
bool RecreateCategoryTree)
{
var dictionary = new Dictionary<string, Guid>();
if (categories.Count == 0)
{
// old export method when only categories ids are exported
var oldExistingCategoriesIds = new List<Guid>();
blogs.Select(t => t.Categories).ForEach(
t =>
{
for (int i = 0; i < t.Count; i++)
{
Guid parsedGuid;
if (Guid.TryParse(t[i].Ref, out parsedGuid) && !oldExistingCategoriesIds.Contains(parsedGuid))
{
oldExistingCategoriesIds.Add(parsedGuid);
}
}
});
oldExistingCategoriesIds = repository.AsQueryable<Category>().Where(t => oldExistingCategoriesIds.Contains(t.Id)).Select(t => t.Id).ToList();
oldExistingCategoriesIds.ForEach(t => dictionary.Add(t.ToString(), t));
return dictionary;
}
if (RecreateCategoryTree)
{
// sort categories that parents would be first
for (int i = 0; i < categories.Count; i++)
{
for (int j = 0; j < categories.Count; j++)
{
if (categories[i].ID == categories[j].ParentRef && i > j)
{
var tmp = categories[j];
categories[j] = categories[i];
categories[i] = tmp;
}
}
}
var newIdsForCategories = new Dictionary<string, Guid>();
// regenerate new ids for category tree
foreach (var category in categories)
{
if (!newIdsForCategories.ContainsKey(category.ID))
{
newIdsForCategories.Add(category.ID, Guid.NewGuid());
}
if (!string.IsNullOrEmpty(category.ParentRef) && !newIdsForCategories.ContainsKey(category.ParentRef))
{
newIdsForCategories.Add(category.ParentRef, Guid.NewGuid());
}
}
foreach (var category in categories)
{
category.ID = newIdsForCategories[category.ID].ToString();
if (!string.IsNullOrEmpty(category.ParentRef))
{
category.ParentRef = newIdsForCategories[category.ParentRef].ToString();
}
}
var refrencedCategoriesIds = new List<Guid>();
foreach (var blog in blogs)
{
for (int i = 0; i < blog.Categories.Count; i++)
{
var category = blog.Categories[i];
// it may be that category is deleted but it is still linked to blog and that link is not deleted
if (newIdsForCategories.ContainsKey(category.Ref))
{
var newCategoryId = newIdsForCategories[category.Ref];
category.Ref = newCategoryId.ToString();
refrencedCategoriesIds.Add(newCategoryId);
}
}
}
Guid testParseGuid;
var oldIdsCategories = newIdsForCategories.Keys.Where(t => Guid.TryParse(t, out testParseGuid)).Select(t => new Guid(t)).ToList();
var existingCategoriesIdsFuture = repository.AsQueryable<Category>().Select(t => t.Id).Where(t => oldIdsCategories.Contains(t)).ToFuture();
var availableFor = repository.AsQueryable<CategorizableItem>().ToFuture().ToList();
var existingCategoriesIds = existingCategoriesIdsFuture.ToList();
// creates categories trees
foreach (var categoryTree in categories.Where(c => string.IsNullOrEmpty(c.ParentRef)))
{
var newTree = new CategoryTree
{
Title = categoryTree.Title,
CreatedOn = categoryTree.DateCreated,
ModifiedOn = categoryTree.DateModified,
Id = new Guid(categoryTree.ID)
};
newTree.AvailableFor = new List<CategoryTreeCategorizableItem>();
foreach (var categorizableItem in availableFor)
{
newTree.AvailableFor.Add(new CategoryTreeCategorizableItem { CategorizableItem = categorizableItem, CategoryTree = newTree });
}
newCategoriesTreeList.Add(newTree);
}
// create categories
foreach (var category in categories.Where(t => !string.IsNullOrEmpty(t.ParentRef)))
{
var categoryParentId = new Guid(category.ParentRef);
var newParentCategoryTree = newCategoriesTreeList.FirstOrDefault(t => t.Id == categoryParentId);
var newCategory = new Category
{
Name = category.Title,
CreatedOn = category.DateCreated,
ModifiedOn = category.DateModified,
Id = new Guid(category.ID),
CategoryTree = newParentCategoryTree
};
newCategoriesList.Add(newCategory);
}
// set references for category, category tree
foreach (var category in newCategoriesList.Where(t => t.CategoryTree == null))
{
category.CategoryTree = newCategoriesList.First(t => t.Id.ToString() == categories.First(c => c.ID == category.Id.ToString()).ParentRef).CategoryTree;
}
foreach (var tree in newCategoriesTreeList)
{
tree.Categories = newCategoriesList.Where(t => t.CategoryTree != null && t.CategoryTree.Id == tree.Id).ToList();
}
foreach (var child in newCategoriesList)
{
var parentId = new Guid(categories.First(t => t.ID == child.Id.ToString()).ParentRef);
var parentCategory = newCategoriesList.FirstOrDefault(t => t.Id == parentId);
if (parentCategory != null)
{
child.ParentCategory = parentCategory;
parentCategory.ChildCategories = parentCategory.ChildCategories ?? new List<Category>();
parentCategory.ChildCategories.Add(child);
}
}
// generate category for empty category tree
foreach (var categoryTree in newCategoriesTreeList.Where(t => t.Categories != null && t.Categories.Count == 0))
{
var category = new Category
{
Id = categoryTree.Id,
CreatedOn = categoryTree.CreatedOn,
ModifiedOn = categoryTree.ModifiedOn,
Name = categoryTree.Title,
CategoryTree = categoryTree
};
categoryTree.Id = Guid.NewGuid();
categoryTree.Categories.Add(category);
newCategoriesList.Add(category);
}
// removing referenced categories that they would not be saved and adding existing category id from db
foreach (var existingCategoriesId in existingCategoriesIds)
{
refrencedCategoriesIds.Remove(newIdsForCategories[existingCategoriesId.ToLowerInvariantString()]);
dictionary.Add(existingCategoriesId.ToString(), existingCategoriesId);
foreach (var blog in blogs)
{
for (int i = 0; i < blog.Categories.Count; i++)
{
if (blog.Categories[i].Ref == newIdsForCategories[existingCategoriesId.ToLowerInvariantString()].ToLowerInvariantString())
{
blog.Categories[i].Ref = existingCategoriesId.ToLowerInvariantString();
}
}
}
}
// filter, save only categories who are related to imported blogs
newCategoriesTreeList = newCategoriesTreeList.Where(t => t.Categories.Any(z => refrencedCategoriesIds.Contains(z.Id))).ToList();
newCategoriesList =
newCategoriesList.Where(t => t.CategoryTree != null && t.CategoryTree.Categories.Any(z => refrencedCategoriesIds.Contains(z.Id))).ToList();
// save new records
foreach (var category in newCategoriesList)
{
dictionary.Add(category.Id.ToString(), category.Id);
unitOfWork.Session.Save(category);
}
foreach (var tree in newCategoriesTreeList)
{
unitOfWork.Session.Save(tree);
}
} else if (ReuseExistingCategories)
{
// Get used categories names and ids (key id, value name)
var catNames = new Dictionary<string, string>();
foreach (var blog in blogs)
{
for (int i = 0; i < blog.Categories.Count; i++)
{
var categoryId = blog.Categories[i].Ref;
if (!catNames.ContainsKey(categoryId) && blogs.Any(t => BlogHasCategory(t, categoryId)))
{
catNames.Add(categoryId, (categories.FirstOrDefault(t => t.ID == categoryId) ?? new BlogMLCategory()).Title);
}
}
}
var existingCategoriesByIdsFuture = repository.AsQueryable<Category>().Where(t => catNames.Keys.Contains(t.Id.ToString())).ToFuture();
var existingCategoriesByNamesFuture = repository.AsQueryable<Category>().Where(t => catNames.Values.Contains(t.Name)).ToFuture();
// Get categories by ids
var existingCategoriesByIds = existingCategoriesByIdsFuture.ToList();
// Get categories by names
var existingCategoriesByNames = existingCategoriesByNamesFuture.ToList();
foreach (var catName in catNames)
{
var category = existingCategoriesByIds.FirstOrDefault(t => t.Id.ToLowerInvariantString() == catName.Key);
category = category ?? existingCategoriesByNames.FirstOrDefault(t => t.Name == catName.Value);
if (category != null)
{
dictionary.Add(catName.Key, category.Id);
}
}
}
return dictionary;
}