Módulo:Mooc/AnalisadorIndex

A documentação para este módulo pode ser criada na página Módulo:Mooc/AnalisadorIndex/doc

local Item = require("Módulo:Mooc/Data/Item");

local moocIndex = {}

local function splitLines(stringValue)
  local lines = {}
  for s in stringValue:gmatch("[^\r?\n]+") do
    table.insert(lines, s);
  end
  return lines;
end

local function splitPath(path)
  local name;
  local pathParts = {}
  for s in path:gmatch("[^/]+") do
    table.insert(pathParts, s);
  end
  
  if #pathParts > 1 then
    -- name is last path part
    name = pathParts[#pathParts];
  else
    -- name is full path for root item
    name = path;
  end
  
  return name, pathParts;
end

local function getLevel(itemHeader)
  local leading = string.len(string.match(itemHeader, "^=*"));
  local trailing = string.len(string.match(itemHeader, "=*$"));
  return math.min(leading, trailing);
end

local function isItem(header, itemName, itemType)
  if header:getName() == itemName then
    if itemType == nil or itemType:isType(header:getTypeIdentifier()) then
      return true;
    end
  end
  return false;
end

local function loadParam(textLines, iParamStart)
  local line = textLines[iParamStart];  
  if line ~= nil and string.sub(line, 1, 1) == "*" then
    local iSeparator = string.find(line, "=", 2, true);
    if iSeparator ~= nil then
      local paramLines = nil;
      local paramName = string.sub(line, 2, iSeparator - 1);
      
      local i = iParamStart;
      local paramValue = string.sub(line, iSeparator + 1);
      local numLines = #textLines;
      repeat
        if i > iParamStart then
          if paramLines == nil then
            paramLines = {}
            if string.len(paramValue) > 0 then
              table.insert(paramLines, paramValue);
            end
          end
          table.insert(paramLines, line);
        end
        i = i + 1;
        line = textLines[i];
      until i > numLines or string.sub(line, 1, 1) == "*" or getLevel(line) > 0;
      
      if paramLines ~= nil then
        paramValue = table.concat(paramLines, '\n');
      end
      
      return {
        name = paramName,
        value = paramValue,
        iEnd = i
      }
    end
  else
    return nil;
  end
end

local function loadParams(textLines, iItemStart)
  local params = {}
  local iParamStart = iItemStart + 1;
  local numLines = #textLines;
  
  local param;
  repeat
    param = loadParam(textLines, iParamStart);
    if param ~= nil then
      params[param.name] = param.value;
      iParamStart = param.iEnd;
    end
  until param == nil or iParamStart > numLines;
  
  return params, iParamStart;
end

local function extractItem(textLines, iItemStart, parent, maxLevel, section)
  local section = section + 1;
  local header = Item.parseHeader(textLines[iItemStart], parent);
  header:setSection(section);
  local item = Item(header);
  local params;
  
  local nextMaxLevel = 0;
  if maxLevel > 0 then
    nextMaxLevel = math.max(1, maxLevel - 1);
  end
  
  -- load parameters
  local i;
  params, i = loadParams(textLines, iItemStart);
  item:setParams(params);
  
  local itemLevel = item:getLevel();
  local child;
  local numLines = #textLines;
  if maxLevel == 0 or maxLevel > 1 then
    -- extract direct children
    while i <= numLines do
      local level = getLevel(textLines[i]);
      if level > itemLevel then
        -- add child
        child, i, section = extractItem(textLines, i, item, nextMaxLevel, section);
        item:addChild(child);
      else
        -- no child
        break;
      end
    end
  else
    -- skip all children
    while i <= numLines do
      local level = getLevel(textLines[i]);
      if level > 0 then
        if level <= itemLevel then
          break;
        end
      	section = section + 1;
      end
      i = i + 1;
    end
  end
  
  return item, i, section;
end

local function extractIndex(baseItem, searchPath, searchLevel)
  local targetLevel = #searchPath;
  local index = nil;
  
  if searchLevel == targetLevel then
    -- current item is target item
    local index = {}
    index["item"] = baseItem;
    return index;
  end
  
  if baseItem:getChildren() ~= nil then
    -- search at next level
    local previous = nil;
    for _,child in ipairs(baseItem:getChildren()) do
      if isItem(child, searchPath[searchLevel + 1]) then
        -- child is part of search path
        index = extractIndex(child, searchPath, searchLevel + 1);
      elseif searchLevel == targetLevel - 1 then
        -- child may be next or previous item
        if index == nil then
          -- child may be previous item
          previous = child;
        else
          -- child is next item
          index["next"] = child;
          break;
        end
      end
    end
    
    if searchLevel == targetLevel - 1 and index ~= nil and searchLevel > 0 then
      -- current item is parental item
      index["parent"] = baseItem;
      index["previous"] = previous;
    end
  end
  
  return index;
end

function moocIndex.parseIndexOverview(indexPlain, rootPath)
	local textLines = splitLines(indexPlain);
	local rootItem = Item(Item.Header("MOOC", 'mooc', nil, rootPath, 0));
	rootItem:setParams({});
		
	-- extract all index item down to target level
	local i = 1;
	local section = 0;
	local item;
	local numLines = #textLines;
	while i <= numLines do
  		local level = getLevel(textLines[i]);
		if level > 0 then
			item, i, section = extractItem(textLines, i, rootItem, 2, section);
			rootItem:addChild(item);
		else
			-- skip initial lines
			i = i + 1;
		end
	end

	local index = {}
	index['item'] = rootItem;
	
	return index;
end

function moocIndex.parseIndex(indexPlain, itemPath, rootPath)
  local textLines = splitLines(indexPlain);
  local itemName, itemPath = splitPath(itemPath);
  local targetLevel = #itemPath;
  local rootItem = Item(Item.Header("MOOC", 'mooc', nil, rootPath, 0));
  
  -- extract all index item down to target level
  local i = 1;
  local section = 0;
  local item;
  local numLines = #textLines;
  while i <= numLines do
    local level = getLevel(textLines[i]);
    if level > 0 then
      item, i, section = extractItem(textLines, i, rootItem, targetLevel + 1, section);
      rootItem:addChild(item);
    else
      -- skip initial lines
      i = i + 1;
    end
  end
  
  -- find target item
  local index = extractIndex(rootItem, itemPath, 0);
  if index ~= nil then
  	index["navigation"] = rootItem;
  end

  return index;
end

return moocIndex;