You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
2.4 KiB
115 lines
2.4 KiB
const ROOT_NAMESPACE_NAME = '__rootNamespace__'; |
|
|
|
class Namespace { |
|
constructor(name, parentNamespace) { |
|
this.name = name; |
|
this.parentNamespace = parentNamespace; |
|
this.childNamespaces = {}; |
|
this.tasks = {}; |
|
this.rules = {}; |
|
this.path = this.getPath(); |
|
} |
|
|
|
get fullName() { |
|
return this._getFullName(); |
|
} |
|
|
|
addTask(task) { |
|
this.tasks[task.name] = task; |
|
task.namespace = this; |
|
} |
|
|
|
resolveTask(name) { |
|
if (!name) { |
|
return; |
|
} |
|
|
|
let taskPath = name.split(':'); |
|
let taskName = taskPath.pop(); |
|
let task; |
|
let ns; |
|
|
|
// Namespaced, return either relative to current, or from root |
|
if (taskPath.length) { |
|
taskPath = taskPath.join(':'); |
|
ns = this.resolveNamespace(taskPath) || |
|
Namespace.ROOT_NAMESPACE.resolveNamespace(taskPath); |
|
task = (ns && ns.resolveTask(taskName)); |
|
} |
|
// Bare task, return either local, or top-level |
|
else { |
|
task = this.tasks[name] || Namespace.ROOT_NAMESPACE.tasks[name]; |
|
} |
|
|
|
return task || null; |
|
} |
|
|
|
|
|
resolveNamespace(relativeName) { |
|
if (!relativeName) { |
|
return this; |
|
} |
|
|
|
let parts = relativeName.split(':'); |
|
let ns = this; |
|
|
|
for (let i = 0, ii = parts.length; (ns && i < ii); i++) { |
|
ns = ns.childNamespaces[parts[i]]; |
|
} |
|
|
|
return ns || null; |
|
} |
|
|
|
matchRule(relativeName) { |
|
let parts = relativeName.split(':'); |
|
parts.pop(); |
|
let ns = this.resolveNamespace(parts.join(':')); |
|
let rules = ns ? ns.rules : []; |
|
let r; |
|
let match; |
|
|
|
for (let p in rules) { |
|
r = rules[p]; |
|
if (r.match(relativeName)) { |
|
match = r; |
|
} |
|
} |
|
|
|
return (ns && match) || |
|
(this.parentNamespace && |
|
this.parentNamespace.matchRule(relativeName)); |
|
} |
|
|
|
getPath() { |
|
let parts = []; |
|
let next = this.parentNamespace; |
|
while (next) { |
|
parts.push(next.name); |
|
next = next.parentNamespace; |
|
} |
|
parts.pop(); // Remove '__rootNamespace__' |
|
return parts.reverse().join(':'); |
|
} |
|
|
|
_getFullName() { |
|
let path = this.path; |
|
path = (path && path.split(':')) || []; |
|
path.push(this.name); |
|
return path.join(':'); |
|
} |
|
|
|
isRootNamespace() { |
|
return !this.parentNamespace; |
|
} |
|
} |
|
|
|
class RootNamespace extends Namespace { |
|
constructor() { |
|
super(ROOT_NAMESPACE_NAME, null); |
|
Namespace.ROOT_NAMESPACE = this; |
|
} |
|
} |
|
|
|
module.exports.Namespace = Namespace; |
|
module.exports.RootNamespace = RootNamespace; |
|
|
|
|