Skip to content

Commit

Permalink
(#13) Introduce LinkedHashMap
Browse files Browse the repository at this point in the history
  • Loading branch information
Andy Tang committed Jan 25, 2014
1 parent 4d97e34 commit bd17830
Show file tree
Hide file tree
Showing 6 changed files with 439 additions and 12 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,12 @@ pip-log.txt

test-results.xml

node_modules

#############
## Coverage
#############
/coverage
/coverage/*.*
/coverage/**/*.*
/coverage/**/**/*.*
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ Examples
--------
Declaring an empty class

var Animal = Class(function Animal() {
var Animal = clazz(function Animal() {

});

var animal = new Animal();

Declaring private scope

var Animal = Class(function Animal() {
var Animal = clazz(function Animal() {
this.private = {
privateFoo: 'foo',
privateBar: function privateBar() {
Expand All @@ -47,7 +47,7 @@ Declaring private scope

Declaring public scope

var Animal = Class(function Animal() {
var Animal = clazz(function Animal() {
this.public = {
publicFoo: 'foo',
publicBar: function privateBar() {
Expand All @@ -60,7 +60,7 @@ Declaring public scope

Declaring protected scope

var Animal = Class(function Animal() {
var Animal = clazz(function Animal() {
this.protected = {
protectedFoo: 'foo',
protectedBar: function privateBar() {
Expand All @@ -73,7 +73,7 @@ Declaring protected scope

Declaring a constructor

var Animal = Class(function Animal() {
var Animal = clazz(function Animal() {
this.private = {
privateFoo: null,
privateBar: function privateBar() {
Expand All @@ -87,7 +87,7 @@ Declaring a constructor

Extending a class

var Animal = Class(function Animal() {
var Animal = clazz(function Animal() {
this.private = {
birthDate: new Date()
};
Expand All @@ -111,7 +111,7 @@ Extending a class
};
});

var Dog = Class(function Dog() {
var Dog = clazz(function Dog() {
this.extend = Animal;

this.constructor = function(birthDate){
Expand Down
2 changes: 1 addition & 1 deletion src/ClassFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* @param NewClass The Class that has to be generated
* @returns {EnoFJSClass} A generated class
*/
window.Class = function Class(NewClass) {
window.clazz = function clazz(NewClass) {
var className = extractClassName(NewClass);

registeredClasses[className] = NewClass;
Expand Down
279 changes: 279 additions & 0 deletions src/LinkedHashMap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
/*
* Copyright (c) 2014.
*
* @Author Andy Tang
*/
(function LinkedHashMapScope(window, clazz, undefined) {
'use strict';

/**
* A node containing a key value pair
* @type {Node}
*/
var Node = clazz(function Node() {
this.private = {
key: null,
value: null,
previous: null,
next: null
};

this.public = {
getKey: function getKey() {
return this.private.key;
},
setKey: function setKey(key) {
this.private.key = key;
},
getValue: function getValue() {
return this.private.value;
},
setValue: function setValue(value) {
this.private.value = value;
},
getPrevious: function getPrevious() {
return this.private.previous;
},
setPrevious: function setPrevious(previous) {
this.private.previous = previous;
},
getNext: function getNext() {
return this.private.next;
},
setNext: function setNext(next) {
this.private.next = next;
}
};

this.constructor = function constructor(key, value) {
this.private.key = key;
this.private.value = value;
};
});

/**
* LinkedHashMap contains a map of key and a Node
* The Node will have a reference to the neighbour nodes,
* similar to a LinkedList
*
* @type {LinkedHashMap}
*/
window.LinkedHashMap = clazz(function LinkedHashMap() {
this.private = {
duplicateKeyError: 'key already exists in LinkedHashMap',
keyNotFoundError: 'key not found',
count: 0,
first: null,
last: null,
hashMap: {},

/**
* Add a new entry to the hashMap
*
* @throws key already exists in LinkedHashMap
* @param key {Integer|String} the key that will be used to reference the node
* @param value {*}the value that will be stored in the node
* @returns {Node}
*/
add: function add(key, value) {
if (this.private.hashMap.hasOwnProperty(key)) {
throw new Error(this.private.duplicateKeyError);
}
var newNode = new Node(key, value);
this.private.hashMap[key] = newNode;
this.private.count++;
return newNode;
},

/**
* Remove an entry from the hashMap and removes all
* references to the node to be removed
* @param node {Node} the node that will be removed
*/
remove: function remove(node) {
var key = node.getKey();
if (node === this.private.first) {
this.private.first = this.private.first.getNext();
this.private.first.setPrevious(null);
} else if (node === this.private.last) {
this.private.last = this.private.last.getPrevious();
this.private.last.setNext(null);
} else {
node.getPrevious().setNext(node.getNext());
node.getNext().setPrevious(node.getPrevious());
}
delete this.private.hashMap[key];
}
};

this.protected = {

/**
* Adds a new node after the given node
*
* @param node {Node} a reference node where the new node will be added after
* @param newNode {Node} the new node to be added
*/
addAfter: function addAfter(node, newNode) {
var nextNode = node.getNext();
if (nextNode !== null) {
nextNode.setPrevious(newNode);
newNode.setNext(nextNode);
}
node.setNext(newNode);
newNode.setPrevious(node);
},

/**
* Adds a new node before the given node
*
* @param node {Node} a reference node where the new node will be added before
* @param newNode {Node} the new node to be added
*/
addBefore: function addBefore(node, newNode) {
var previousNode = node.getPrevious();
if (previousNode !== null) {
previousNode.setNext(newNode);
newNode.setPrevious(previousNode);
}
node.setPrevious(newNode);
newNode.setNext(node);
}
};

this.public = {

/**
* Add a new key value pair to the LinkedHashMap
* The newly added node will update the last node to point to
* this new node.
*
* @throws key already exists in LinkedHashMap
* @param key {Integer|String} the key which will serve as a reference point
* @param value {*} the value to be stored
* @returns {Node}
*/
add: function add(key, value) {
var newNode = this.private.add(key, value);
if (this.private.count === 1) {
this.private.first = newNode;
} else {
this.protected.addAfter(this.private.last, newNode);
}
this.private.last = newNode;

return newNode;
},

/**
* Adds a new node after a given node key
*
* @param nodeKeyToInsertAfter {Integer|String} the key of the node
* the new node has to be added after
* @param newKey {Integer|String} the key of the new node
* @param newValue {*} the value of the new node
* @throws key not found
* @returns {Node}
*/
addAfter: function addAfter(nodeKeyToInsertAfter, newKey, newValue) {
var newNode = this.private.add(newKey, newValue);
var nodeToInsertAfter = this.public.getById(nodeKeyToInsertAfter);
this.protected.addAfter(nodeToInsertAfter, newNode);
return newNode;
},

/**
* Adds a new node before a given node key
*
* @param nodeKeyToInsertBefore {Integer|String} the key of the node
* the new node has to be added before
* @param newKey {Integer|String} the key of the new node
* @param newValue {*)
* @throws key not found
* @returns {Node}
*/
addBefore: function addBefore(nodeKeyToInsertBefore, newKey, newValue) {
var newNode = this.private.add(newKey, newValue);
var nodeToInsertBefore = this.public.getById(nodeKeyToInsertBefore);
this.protected.addBefore(nodeToInsertBefore, newNode);
return newNode;
},

/**
* Adds a new node at the first position
*
* @param newKey {Integer|String} the key for the new node
* @param newValue {*} the value of the new node
* @returns {Node}
*/
addFirst: function addFirst(newKey, newValue) {
var newNode = this.private.add(newKey, newValue);
var first = this.private.first;
if (first !== null) {
this.protected.addBefore(first, newNode);
}
return newNode;
},

/**
* Adds a new node at the last position
*
* @param newKey {Integer|String} the key for the new node
* @param newValue {*} the value of the new node
* @returns {Node}
*/
addLast: function addLast(newKey, newValue) {
return this.public.add(newKey, newValue);
},

/**
* Gets a node by id (key)
*
* @throws key not found
* @param key {Integer|String} the key of the node
* @returns {Node}
*/
getById: function getById(key) {
var node = this.private.hashMap[key];
if (node === undefined) {
throw new Error(this.private.keyNotFoundError);
}
return node;
},
getFirst: function getFirst() {
return this.private.first;
},
getLast: function getLast() {
return this.private.last;
},
/**
* Removes a node with a given key
*
* @param key {Integer|String} key of the node to be removed
* @returns {}
*/
remove: function remove(key) {
if (!this.private.hashMap.hasOwnProperty(key)) {
return false;
}
return this.private.remove(this.public.getById(key));
},
removeFirst: function removeFirst() {
if (this.private.first === null) {
return false;
}
return this.private.remove(this.private.first);
},
removeLast: function removeLast() {
if (this.private.last === null) {
return false;
}
return this.private.remove(this.private.last);
}
};

this.constructor = function constructor() {

};
});
}(window, window.clazz));
Loading

0 comments on commit bd17830

Please sign in to comment.