Skip to content

Commit

Permalink
Replace hint rotation with goodKeys stack
Browse files Browse the repository at this point in the history
  • Loading branch information
JoelOtter committed May 29, 2016
1 parent 91a43c6 commit 4199ff7
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 39 deletions.
95 changes: 59 additions & 36 deletions lib/reshaper.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ function traverseAndFind(data, searchType, stacks, hints, getFirst) {
// than simply undefined.
return {value: data};
}
var getFirst = (hints === undefined || hints.length === 0) || getFirst;
var newHints;
if (util.typeString(hints) === 'Array') {
newHints = stacks.goodKeys.concat(hints);
} else {
newHints = hints;
}
var getFirst = (newHints === undefined || newHints.length === 0) || getFirst;
switch(dataType) {
case 'Object':
return traverseObject(data, searchType, stacks, hints, getFirst);
Expand All @@ -31,9 +37,6 @@ function traverseObject(object, searchType, stacks, hints, getFirst) {
object[keys[i]], searchType, stacks, hints, true
);
if (first.value !== null && stacks.staleKeys.indexOf(keys[i]) === -1) {
if (hintType === 'Array') {
hints.unshift(keys[i]);
}
if (first.match === undefined) {
first.match = keys[i];
}
Expand All @@ -42,29 +45,45 @@ function traverseObject(object, searchType, stacks, hints, getFirst) {
}
}
// Breadth-first. Let's first look over the members of the object.
for (var h = 0; hintType === 'Array' && h < hints.length; h++) {
var hint = hints[h];
var undotted = hint.split('.');
for (var i = 0; i < keys.length; i++) {
var data = object[keys[i]];
if (undotted.length > 1 &&
(undotted[0] === keys[i] || undotted[0] === '_')) {
// Search this key, unpacking the dotted hint
var dotHinted = traverseAndFind(
data, searchType, stacks, [undotted.slice(1).join('.')], false
);
if (dotHinted.value !== null) {
return dotHinted;
if (hintType === 'Array') {
var newHints = stacks.goodKeys.concat(hints);
for (var h = 0; h < newHints.length; h++) {
var hint = newHints[h];
var undotted = hint.split('.');
for (var i = 0; i < keys.length; i++) {
var data = object[keys[i]];
if (undotted.length > 1 &&
(undotted[0] === keys[i] || undotted[0] === '_')) {
// Search this key, unpacking the dotted hint
var newStacks = {
data: stacks.data,
goodKeys: stacks.goodKeys,
staleKeys: []
};
// First, adjust the staleKeys
for (var j = 0; j < stacks.staleKeys.length; j++) {
var stale = stacks.staleKeys[j];
var split = stale.split('.');
if (split.length > 1 && split[0] === keys[i]) {
newStacks.staleKeys.push(split.slice(1).join('.'));
}
}
var dotHinted = traverseAndFind(
data, searchType, newStacks, [undotted.slice(1).join('.')], false
);
if (dotHinted.value !== null) {
dotHinted.match = hint;
return dotHinted;
}
}
if (util.typeString(data) === searchType && keys[i] === hint &&
stacks.staleKeys.indexOf(hint) === -1) {
return {value: data, match: hint};
}
}
if (util.typeString(data) === searchType && keys[i] === hint) {
// Matches hint - return. Move hint to front of stack.
util.removeFromArray(hints, hints.indexOf(hint));
hints.unshift(hint);
return {value: data};
}
}
}

// If we get to here, we haven't found anything yet. Let's search the children.
for (var i = 0; i < keys.length; i++) {
var hinted = traverseAndFind(
Expand All @@ -89,9 +108,6 @@ function traverseObject(object, searchType, stacks, hints, getFirst) {
object[keys[i]], searchType, stacks, hints, true
);
if (first.value !== null) {
if (hintType === 'Array') {
hints.unshift(keys[i]);
}
if (first.match === undefined) {
first.match = keys[i];
}
Expand Down Expand Up @@ -123,7 +139,8 @@ function extractObject(data, schema, stacks, hints) {
stacks.data.unshift(data);
var newStacks = {
data: stacks.data,
staleKeys: stacks.staleKeys.slice()
staleKeys: stacks.staleKeys.slice(),
goodKeys: stacks.goodKeys.slice()
};
var found = traverseAndFind(data, 'Object', newStacks, hints);
var object = found.value;
Expand Down Expand Up @@ -158,10 +175,6 @@ function extractObject(data, schema, stacks, hints) {
if (extracted.match) {
newStacks.staleKeys.push(extracted.match);
}
// Rotate the current hints (if array)
if (hintType === 'Array' && hints.length > 0) {
hints.push(hints.shift());
}
});
return result;
}
Expand All @@ -170,7 +183,8 @@ function extractArray(data, schema, stacks, hints) {
var arrayOf = schema[0];
var newStacks = {
data: stacks.data,
staleKeys: stacks.staleKeys.slice()
staleKeys: stacks.staleKeys.slice(),
goodKeys: stacks.goodKeys.slice()
};
var array = traverseAndFind(data, 'Array', newStacks, hints);
// Can't find? Might have gone too deep - use stack.
Expand All @@ -187,12 +201,20 @@ function extractArray(data, schema, stacks, hints) {
result.match = array.match;
}
var childExtractor = getExtractionFunction(arrayOf);
var foundMatch;
array.value.forEach(function (item) {
var found = childExtractor(item, arrayOf, newStacks, hints).value;
if (found != null) {
result.value.push(found);
var found = childExtractor(item, arrayOf, newStacks, hints);
if (found.value != null) {
result.value.push(found.value);
if (found.match !== undefined) {
foundMatch = found.match;
if (newStacks.goodKeys.indexOf(found.match) === -1) {
newStacks.goodKeys.unshift(found.match);
}
}
}
});
result.match = foundMatch;
if (result.value.length === 0 && array.match) {
newStacks.staleKeys.push(array.match);
result = extractArray(data, schema, newStacks);
Expand Down Expand Up @@ -233,7 +255,8 @@ function extractBoolean(data, schema, stacks, hints) {
function findShape (data, schema, hint) {
var stacks = {
data: [],
staleKeys: []
staleKeys: [],
goodKeys: []
};
var hintType = util.typeString(hint);
var hints;
Expand Down
4 changes: 2 additions & 2 deletions test/basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ describe('basic', function() {
});
});

it('should not have backoff if hint is provided', function() {
it('should backoff even if hint is missing', function() {
var data = {
thing: {
a: 1,
Expand All @@ -112,7 +112,7 @@ describe('basic', function() {
var schema = {one: 'String', two: 'String'};
expect(reshaper.findShape(data, schema, {one: 'c'})).to.eql({
one: 'e',
two: 'e'
two: 'f'
});

});
Expand Down
2 changes: 1 addition & 1 deletion test/github.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('github popular repos', function() {
}
];
var result = reshaper.findShape(
data.items, schema, ['open_issues', 'stargazers_count', 'name']
data, schema, ['open_issues', 'stargazers_count', 'name']
);
var expd = data.items.map(function (item) {
return {
Expand Down

0 comments on commit 4199ff7

Please sign in to comment.