NM2207 Game Page
Hi, I'm Michelle! This page was created for my NM2207 project!
Do check out my games :) The links are at the top left.
Or you can click here for my final assignment: click here!
Here is a write-up on my final assignment:
Introduction
The game I created for my final assignment is called Survival Instincts. The game involves the player who will navigating through the skies on a helicopter with his/her friend. The first segment of the game involves an animated story that narrates how a storm caused the helicopter to crash. After which, the player blacks out and upon gaining consciousness, realizes that his/her friend had disappeared. The player then has to play the game which involves killing poisonous, exotic flies before it reaches the player at the bottom of the screen. The game ends after the player has stayed alive for 20 seconds, or when the health meter decreases to zero. I decided to create two segments for my assignment – animated story and the game, as I wanted to challenge my skills as well as to be able to make use for the variety of skills that we have learnt throughout the module.
Process
I started off with the HTML layout that I had used for my previous assignment and began modifying it to fit my game. I made use of Javascript library, Raphael.js to create graphics and animation for my game. For instance, I could create rectangles, circles and texts, and tweak the positioning and attributes of these graphics to fit the game. Raphael animation was also used to animate the helicopter and lightning.
I made use of arrays and loops for the rainstorm and flies. For the rainstorm, I created an array of raindrops and looped them for 150 (maxRaindrop) of raindrops. I created a draw function for enabling the raindrops to move by changing its x and y coordinates, and called on that function every 40ms with setInterval. I also referred to the emitter tutorial that we had in class, to enable more raindrops to be created even after 150 (maxRaindrop) raindrops had been created. The “%” operator ensures that the value of i will not exceed 150, hence, the loop will not stop. Similarly, this method was used for creating and looping the array of flies for the fly game. The map and distance functions that we used for assignment 4 came in handy for enabling me to scale the distance for the x and y coordinates and rates for the fly array.
As there were many elements in final assignment, I had to organize my code neatly to avoid confusion. The placement of the variables was also very important as I met with many error messages when variables were not defined globally. Using console messages helped greatly in troubleshooting the errors that I encountered. I realized that it was very important to think calmly and logically about the origin of the error.
If statements were very useful in enabling me to run functions when certain conditions were met. For instance, if the mousedown coordinates is within 100, the fly will be set off-screen and a splat sound will be played. If the fly is very close to the bottom of the screen, a panic alert will sound and some exclamations marks will appear at the bottom right hand corner. If the health value is zero, it will run the Game Over function. If the time runs out and the player is still alive, it will run Survived function, which informs the user that s/he has found his/her friend and civilization. The if statements also enabled me to set the difficulty of the game depending on the selected difficulty level.
Referring to coding platforms such as w3schools.com aided me in improving and trying to find solutions for my game. I was initially trying to create a health bar using a Raphael graphic, but after searching online (https://css-tricks.com/html5-progress-element/), I realized that there is a HTML progress bar element which can be used for health bars in games. Hence, I decided to utilize it and place it outside of my Raphael “paper” to avoid overlapping with the game.
After I had conceptualized the theme and mechanics for my game, I began to sourced for suitable images and sound files for my game to enhance the game experience for the user. All the sound files were sourced from Freesound.org, and I modified the length of the sounds using audio software to fit the game. Timers and event listeners enabled me to play the audios at the appropriate time. Through researching online, I discovered how to make use of a function to gradually decrease volume, so that there is a better transition to the next page.
Further Improvements
In order to enable users to skip the story animation scenes, two buttons were created beside the mySVGCanvas Div. The first button enables the user to skip the storyline, regardless of which scene they are currently in. The drawback of this is that some animation may not have appeared on the screen when the button is clicked, due to setTimeout functions on the scene text and next buttons. To overcome this problem, I included a setTimeout inside of the eventListener to hide all the elements, in case new elements appear after the button was clicked. Another drawback is that error codes will appear if the button is clicked in the first scene, before it starts raining. This is because the rain array is only initialized inside of var scene2. To counter this problem, I created another button is specifically for stopping the rain. The event listener listens for clicks, and will run a function to hide the rain if the rain has started.
During the coding of my game, I faced many challenges and error codes. In particular, I had great difficulty in trying to hide and show the appropriate elements at the correct time. Despite many attempts, I was unable to hide all the flies off the screen after the game ends. The flies that are already on the screen will still stay stationary on that screen after the drawFly interval is cleared. Also, restarting the game works if it was “game over”- new flies will appear. However, if the player survived the game and wanted to replay, new flies do not appear. I regret not being able to fix this bug, but I suspect it may be because the survived function was created outside of the function containing the initialization of the fly array.
To further enhance the game experience, perhaps obstacles could be added into the game to increase difficulty. For instance, clicking on obstacles such as endangered animal species, could result in loss of health, penalty points or an extension of time (i.e having to survive in a longer period of time). Overall, while there is still room for improvement, the coding process was very valuable and challenged my limits.


Invalid Email address
Email already registerd
Invalid User name
Username already registered
Password is required
Confirm Password is required
Password & Confirm Password should be same.
First name is required
Last name is required
Home Phone is required
Mobile is required


---
layout: post
title: "I finally rewrote my resume. In LaTeX."
description: ""
category:
tags: [LaTeX, resume]
comments: true
---
I had been needing to rewrite my resume for a while. I've always had it in a doc file of course but I wanted to be super nerd-o and update it in LaTeX. And here it is!
 (Which is apparently pronounced /ˈlɑːtɛk/ or if you don't read dictionary, lay-tek). I've published it on Github (link) if you'd like to fork it and write your own resume in LaTeX. The code and resulting compiled PDF are below. Let me know what you think!
The code:
The compiled result:


In May 2019 State Secretaty of Safety Mark Harbers in combination with the police released a concerning asylum seekers and criminality.
However, Harbers played with the numbers in the rapport. Serious crimes were worked away in the numbers
The report had hidden the numbers of asylum seekers for suspected for serious crimes such as rape and murder under the heading 'other'
and were therefore not included in the top 10 crimes for which asylum seekers were suspected..
This, of course, led to a lot of upproar in The Netherlands.
The article can be found
here.
We live in times where people are afraid, especially of people who are different or come from another place than ours.
This in combination with lack of knowledge of the actual numbers of crime, asylum seekers and migrants have lead to forgone
conclusions and fear/anger in many people towards "foreigners".
The goal of creating these visualisations is to better show people the numbers about immigrants and people with immigrant backgrounds and crimes.
Hopefully, showing that immigrants do not always "commit crimes" and eventually change people's perceptions about migrants. But that's for yourselves to judge.
We all might just get along after all.


All Classes
AsmExpression
Assembler
Assembler1
Assembler2
Assembler3
Command
Comment
Environment
Instruction
Instruction1
Instruction2
Instruction3
Label
Symbol
Symbol.Type


Hi,
I'm new to the whole OEM thing, so please be gentle.
I've got Debian 7 running in a VM on Windows. I've installed emoncms (had to do a manual install since I couldn't get the app package to install) and it is up on my local web server. I've created a test bed for the eMonTx and I can connect from Debian to the JeeLink and get data from the eMonTx.
What I am having trouble with is getting the data from the Jeelink to Emoncms. I've seen some 'conflicting' articles or forum posts which seem to suggest OEMGateway is the suggested method to get the data. However I had seen others which mention possibly an internal method for Emoncms to get it. So I guess my first question is to confirm whether I need OEMGateway or whether there is a simple equivalent already packaged with Emoncms?
Assuming OEMGateway is the recommended method, I've tried to use OEMGateway and using the config I found in a forum post I've put an listener entry in the config with a type of EmonhubJeelink. However when I run the gateway it complains that there is no such type. I've reviewed the oemgatewaylistener.py script and can see the other classes defined, but sure enough not the Jeelink one. Do I need a different or custom interface script (that I haven't been able to find online) or should I be using a different standard class/type eg. OemGatewayRFM2PiListener?
Thanks in advance,
Jason
Re: Jeelink, eMonTx, Debian and OEMGateway
Hi Jason, There have been various "input interfaces" for emonCMS but currently the only recommended approach is to use emonHub. OEM Gateway was emonHub's predecessor and both the "raspberrypi" module for emoncms and the "emoncms-module-rfm2pi" debian package have been retired to focus on the 1 interface.
emonHub will work with jeelink, I use one myself with emonHub, on a windows PC.
There is more info on how to install emonHub in the Emonhub installation/update thread and to use the JeeLink you will need to make some minor changes in settings to redirect the rfm2pi interfacer to the usb port, you can also rename it if you prefer, if you were using a Pi I would of said create a new interfacer like the rfm2pi interfacer, but since you are on a pc, I assume you have no need for the rfm2pi interfacer so it may as well be altered, either way you need to end up with settings along the lines of
[[JeeLink]]
Type = EmonHubJeeInterfacer
[[[init_settings]]
com_port = /dev/ttyUSB0
[[[runtimesettings]]]
group = 210
baseid = 15
frequency = 433
edit the usb port address if required and the group, baseid and frequency in the example are also the default values so can be omitted unless you wish to use a different setting.
You will need to add your emoncms apikey etc much the same as you did with OEMG.
Paul
Re: Jeelink, eMonTx, Debian and OEMGateway
Thanks for your help Paul.
With a bit of mucking around I've got emonhub reading from the Jeelink/emonTx. I've posted another question about why emonhub is reporting dropping invalid frames.
One comment I might make with link you sent me above, it makes mention of dev-emonhub on github. In looking for the 'release version' I found the emonhub project (https://github.com/emonhub/emonhub) and the readme it has a link to the 'release version', which has an empty project and a link to another website with some more circular links back to other documentation and the OEM website (from memory).
I guess I'm wondering is there a 'release' version of emonhub or should people just be taking a cut from the dev project?
Regards,
Jason
Re: Jeelink, eMonTx, Debian and OEMGateway
Hi Jason, The original plan was to release emonHub as a debian package, so the "Master" branch on github was reserved for the "released version", however the debian thing hasn't happened (yet) and emonHub didn't get formally released as such, the "dev" version got included on the SD card image and well, here we are.
Apologies for the lack of documentation too, I did begin work on a documentation website, but took it down as it was incomplete and development took priority as emonHub was gaining pace.
Paul
Re: Jeelink, eMonTx, Debian and OEMGateway
Hi Paul,
Thanks for your continued support. I was thinking about documenting my experience so that it might help future nubes. If you are interested I'll send you a copy and if you think it is useful then perhaps we can find an appropriate place to post it.
Last night I also decided that I would like to extract my Solar PV data from PVOutput.org. I've seen plenty of posts wanting to extract data from emoncms and sent to PVOutput, but not the other way around. I've started writing a script which may be useful to others. I'll see how it goes.
Regards,
Jason
Re: Jeelink, eMonTx, Debian and OEMGateway
Any additional documentation is helpful as it is always a bit thin, there is very little on the JeeLink.
I'm sure there would other users that would find a tool to extract PVOutput data useful so do keep us posted.


Bafana star Zungu almost loses his house – report
Bongani Zungu reportedly almost lost his house after he failed to pay the monthly instalment for 12 months.
Bongani Zungu during the South African national men's soccer team press conference. (Photo by Gallo Images)
According to the Sunday World, the Bafana Bafana midfielder, who is based in France, missed payments on his home in Kempton Park.
According to the court papers Zungu received a R1 120 000 loan from the bank to buy the property and agreed to play a monthly instalment of R15 000 but failed to do so for 12 months.
“The plaintiff placed 36 telephone calls to the defendant to discuss bringing the defendant’s arrears under the loan agreement to date. The plaintiff’s attorneys attempted to reach a payment arrangement with the defendant on four separate occasions,” read the papers as reported by the Sunday World.
“The plaintiff [also] transmitted 20 text messages to the defendant, requesting the defendant to bring his arrears up to date, alternatively to contact the plaintiff to conclude a payment arrangement.
“The defendant had failed to make payment of the full monthly instalment amount due under the loan agreement and was consequently in breach of the loan agreement. The defendant first fell into arrears… on or about 31 May 2018.”
Thulani Thuswa of Tyler Masons Management confirmed that Zungu had missed the payments but added that the Bafana star settled his debt after being contacted by the bank lawyers.
“It was a clear mix-up and a lack of communication as his account couldn’t be debited because he changed his banking details when he moved to France.”


Developed by
jsrath
Bankroll Currency Converter
Amount
From
To
Date
Currency Chart
to
1 Month
3 Months
6 Months
1 Year


Pro-MAM Accreditation PhantomP
| Stock # | Description | Price | |
|---|---|---|---|
| 03-501 | Pro-MAM Accreditation - ACR Compliant | $892.50 | |
| 03-501-CS | Case with foam for above | $80.00 | |
| 03-501-WC | Pro-MAM Accreditation - ACR Compliant - includes foam case | $952.50 | |
| 03-501-SP | Support plate for above | $60.00 |
This phantom was designed to meet ACR Mammography Accreditation Program Requirements as well as those of Mammography Quality Standards Act (MQSA) of 1992. Phantom can test the performance of a mammographic system and its ability to image small structures similar to those found clinically: calcifications, fibrous calcifications in ducts and tumor masses.
TECHNICAL DATA:
Dimensions: 102.0mm x 108.0mm x 44.0mm (4.01" x 4.25" x 1.73")
Simulates 42 mm compressed breast of average glandular/adipose composition
Total PMMA thickness: 36.75 mm (1.45")
Wax Insert
Thickness: 7.25MM
Nylon fibrils diameters: 1.56, 1.12, 0.89, 0.75, 0.54 and 0.40mm
Micro-calcifications: 0.54, 0.40, 0.32, 0.24 and 0.16 mm Al2O3 specks
Tumor-like Masses: 2.00, l.00, 0.75, 0.50 and 0.25 mm thick
4mm thick PMMA contrast disc
Rotating support plate (optional)
Comfortable carrying case (optional)
PRODUCT FEATURES:
Complies with: IEC 61223-3-2
Meets ACR Mammography Accreditation Program Requirements
CE Certified
Manual includes detailed guidelines for carrying out each test, results assessment & registration.
TECHNICAL DATA:
Dimensions: 102.0mm x 108.0mm x 44.0mm (4.01" x 4.25" x 1.73")
Simulates 42 mm compressed breast of average glandular/adipose composition
Total PMMA thickness: 36.75 mm (1.45")
Wax Insert
Thickness: 7.25MM
Nylon fibrils diameters: 1.56, 1.12, 0.89, 0.75, 0.54 and 0.40mm
Micro-calcifications: 0.54, 0.40, 0.32, 0.24 and 0.16 mm Al2O3 specks
Tumor-like Masses: 2.00, l.00, 0.75, 0.50 and 0.25 mm thick
4mm thick PMMA contrast disc
Rotating support plate (optional)
Comfortable carrying case (optional)
PRODUCT FEATURES:
Complies with: IEC 61223-3-2
Meets ACR Mammography Accreditation Program Requirements
CE Certified
Manual includes detailed guidelines for carrying out each test, results assessment & registration.


Junior Bok coach looking forward to Georgian adventure
Cape Town - Junior Springbok coach Chean Roux, who will guide the South Africa Under-19 team on a two-match tour to Georgia, said they were looking forward to the challenge in Tbilisi, with the players and coaching staff set to benefit from the experience.
From the players’ perspective, it will mark the first time some of them participate in an overseas tour, while Roux and his assistant coaches will get good insight into what their charges have to offer on the field under pressure and outside of their comfort zones.
The squad gathered at the Stellenbosch Academy of Sport on Sunday and took the field for the first time on Monday morning.
They will continue their preparations in Stellenbosch until Wednesday, with the squad set to depart for the Georgian capital later that evening.
They will face the Georgian under-19 team in two matches, on December 2 and 5.
“It is good to get the players together and to be back on the field,” said Roux.
“Some of them come off a season-ending break and others from pre-season programmes at their provincial unions, so they are at different stages of training at this point. But the enthusiasm in the squad is high, and that is all we can ask for.”
Roux said they were looking forward to seeing how the players adapt to the new environment and cold conditions in Georgia: “This tour originated from an invitation from Georgia to come on tour and play two matches against their junior teams, and it replaces our usual Under-18 and Under-19 assessment camps.
“It will certainly push us out of our comfort zones because it is not only another country, but we will also be playing in very cold conditions. So it will be a good adventure.
“For the coaches, in particular, it will offer us an opportunity to learn a lot more about the players than that which we would generally see at training camps in Stellenbosch and Potchefstroom for example, so it is going to be a fantastic experience.”
Looking at the bigger picture with the eye on the future, Roux added: “SA Rugby has a few plans, especially with the new contracting model, and these types of camps and tours gives us good insight into where the talent is and where the shortcomings are. And that is exactly what we would like to achieve from this tour. So we are looking forward to it.”
- SA Rugby


class Connection implements ConnectionInterface
Methods
|
__construct($name, $host, $username, array $auth, GatewayInterface $gateway = null)
Create a new SSH connection instance. |
||
| void |
define(string $task, string|array $commands)
Define a set of commands as a task. |
|
| void |
task(string $task, Closure $callback = null)
Run a task against the connection. |
|
| void |
run(string|array $commands, Closure $callback = null)
Run a set of commands against the connection. |
|
| void |
put(string $local, string $remote)
Upload a local file to the server. |
|
| void |
putString(string $remote, string $contents)
Upload a string to to the given file on the server. |
|
| void |
display(string $line)
Display the given line using the default output. |
|
| int|bool |
status()
Get the exit status of the last command. |
|
| GatewayInterface |
getGateway()
Get the gateway implementation. |
|
| OutputInterface |
getOutput()
Get the output implementation for the connection. |
|
| void |
setOutput(OutputInterface $output)
Set the output implementation. |
Details
at line 69
public
__construct($name, $host, $username, array $auth, GatewayInterface $gateway = null)
Create a new SSH connection instance.
at line 84
public void
define(string $task, string|array $commands)
Define a set of commands as a task.
at line 96
public void
task(string $task, Closure $callback = null)
Run a task against the connection.
at line 111
public void
run(string|array $commands, Closure $callback = null)
Run a set of commands against the connection.
at line 140
public void
put(string $local, string $remote)
Upload a local file to the server.
at line 152
public void
putString(string $remote, string $contents)
Upload a string to to the given file on the server.
at line 163
public void
display(string $line)
Display the given line using the default output.
at line 203
public int|bool
status()
Get the exit status of the last command.
at line 213
public GatewayInterface
getGateway()
Get the gateway implementation.
at line 228
public OutputInterface
getOutput()
Get the output implementation for the connection.
at line 241
public void
setOutput(OutputInterface $output)
Set the output implementation.


This controls the gain of the bass section of the virtual {_instrument instrument's} parametric equalizer.
This is contained in the {Control_tone_cluster tone cluster} within the {Control_section}.
This is manipulated by the BASS slider on the left panel. When any of the five short sliders is moved, the display shows their values for a couple seconds. Press PARAM SELECT if you want to see these settings without moving the sliders.
This is accessed via {_NRPN} 0,16. Since it is a {_bipolar} parameter, the values are offset by 64.
| MIDI | display | ||
| 49 | \-15db | ||
| \b\n\b\n\b | \b\n\b\n\b | ||
| 64 | 0db | (default) | |
| \b\n\b\n\b | \b\n\b\n\b | ||
| 79 | +15db |


Id = 338
Nombre Personajen = Summer Smith
Status = Alive
Specie = Human
Origen = Earth (C-137)
Tipo =
Locacion = Earth (C-137)
Id Locacion = ['1']
Episodio = ['https://rickandmortyapi.com/api/episode/1', 'https://rickandmortyapi.com/api/episode/2', 'https://rickandmortyapi.com/api/episode/3', 'https://rickandmortyapi.com/api/episode/4', 'https://rickandmortyapi.com/api/episode/5', 'https://rickandmortyapi.com/api/episode/6', 'https://rickandmortyapi.com/api/episode/22']
Id Episodio = ['1', '2', '3', '4', '5', '6', '22']
URL Personaje = https://rickandmortyapi.com/api/character/338


Taiwan to buy more from U.S. as seeks to head off currency manipulator label-sources
TAIPEI, Nov 25 (Reuters) - Taiwan's central bank and Ministry of Economic Affairs have set up a group to coordinate stepped up purchases of U.S. goods, two sources said, as its seeks to narrow its trade surplus and head off being labelled a currency manipulator.
Taiwan was last labelled a currency manipulator by the United States in December 1992 and was then on the U.S. Treasury monitoring list in 2016 and 2017.
Taiwan's trade surplus with the United States this year is expected to pass $20 billion, meeting one of the criteria Washington uses to decide the monitoring list for a currency manipulator. Taiwan's current account surplus is 11% of GDP, which also matches another criteria to be labelled a currency manipulator, as the threshold is 2%. (Reporting by Liang-sa Loh; Writing by Ben Blanchard; Editing by Himani Sarkar)
© Copyright Thomson Reuters 2019. Click For Restrictions - http://about.reuters.com/fulllegal.asp


There is a flexibility given to include JavaScript code anywhere in an HTML document. However the most preferred ways to include JavaScript in an HTML file are as follows −
Script in ... section.
Script in ... section.
Script in ... and ... sections.
Script in an external file and then include in ... section.
In the following section, we will see how we can place JavaScript in an HTML file in different ways.
If you want to have a script run on some event, such as when a user clicks somewhere, then you will place that script in the head as follows −
     <input type="button" onclick="sayHello()" value="Say Hello" />
This code will produce the following results −
If you need a script to run as the page loads so that the script generates content in the page, then the script goes in the  portion of the document. In this case, you would not have any function defined using JavaScript. Take a look at the following code.

This is web page body

This code will produce the following results −
You can put your JavaScript code in  and  section altogether as follows −
      <input type="button" onclick="sayHello()" value="Say Hello" />
This code will produce the following result −
As you begin to work more extensively with JavaScript, you will be likely to find that there are cases where you are reusing identical JavaScript code on multiple pages of a site.
You are not restricted to be maintaining identical code in multiple HTML files. The script tag provides a mechanism to allow you to store JavaScript in an external file and then include it into your HTML files.
Here is an example to show how you can include an external JavaScript file in your HTML code using script tag and its src attribute.
     .......
To use JavaScript from an external file source, you need to write all your JavaScript source code in a simple text file with the extension ".js" and then include that file as shown above.
For example, you can keep the following content in filename.js file and then you can use sayHello function in your HTML file after including the filename.js file.
function sayHello() { alert("Hello World") }


RT @darinrs: X-Ray sessions support ( http://blog.newrelic.com/2013/04/10/x-ray-sessions/ ) out today in the @NewRelic Ruby agent 3.6.8: https://docs.newrelic.com/docs/releases/ruby
10/9/2013, 4:16:45 PM
Favs: 0
Retweets: 0
link--- layout: tweet ---
RT @darinrs: X-Ray sessions support ( http://blog.newrelic.com/2013/04/10/x-ray-sessions/ ) out today in the @NewRelic Ruby agent 3.6.8: https://docs.newrelic.com/docs/releases/ruby
10/9/2013, 4:16:45 PM
Favs: 0
Retweets: 0
link


--- layout: post title: Microsoft Dynamics Still Killing It During Difficult Quarter for Redmond date: '2012-01-19T16:27:32-08:00' tags: tumblr_url: http://alexhwilliams.tumblr.com/post/16142349682/microsoft-dynamics-still-killing-it-during-difficult ---


Core: http://repository.codehaus.org/org/picocontainer/picocontainer/
Gems: http://repository.codehaus.org/org/picocontainer/picocontainer-gems/
Distribution: http://repository.codehaus.org/org/picocontainer/picocontainer-distribution/
(Current work in progress)
Core: http://snapshots.repository.codehaus.org/org/picocontainer/picocontainer/
Gems: http://snapshots.repository.codehaus.org/org/picocontainer/picocontainer-gems/
Distribution: http://snapshots.repository.codehaus.org/org/picocontainer/picocontainer-distribution/
Currently, the Core jar is ~247K, and the Gems jar is ~112K. The distribution zip contains all jars and documentation.
If you use Maven as the build system (or one that is compatible with the Maven Repository), you can declare dependencies as
org.picocontainer picocontainer[-gems] [version]
specifying the version. Declaring this dependency will pull in all other required dependencies (ie transitive dependencies). Note that PicoContainer core artifactId is simply "picocontainer".


Dog
Cat
Other
Select an Image


Pallister says Canada can unite on climate action if partisan politics set aside
by The Canadian Press, StaffOTTAWA - Manitoba Premier Brian Pallister says the fight against climate change can unite this country even as it currently is fuelling talk of Alberta separation.
Pallister is in Ottawa today to meet with Prime Minister Justin Trudeau and climate change is a critical part of the conversation.
Trudeau's relationship with many provincial premiers is tense, particularly over his decision to impose a price on pollution in any province without an equivalent system of its own, including Manitoba.
Pallister opposes Trudeau's plan, but not carbon taxes in general and is still hoping the prime minister will allow provinces to create their own plans to reduce greenhouse gas emissions.
He is however trying to set himself up as the middle man who could broker a truce between Trudeau and the more strident premiers like Alberta's Jason Kenney and Saskatchewan's Scott Moe.
He says Trudeau's partisan nature and insistence on carbon taxes done his way created divisions about climate change action during the recent federal election rather than finding ways to unite the country behind this critical issue.


This is the partial for view 2, as a common partial.
Showing of 'interpolate' filter: {{ 'Current version is v%VERSION%.' | interpolate }}
AngularJS, sample not existing "message" property from controller: {{ctrl.message}}
AngularJS, sample "foo" property from controller: {{ctrl.foo}}


18 May 2021
This document describes the “Sample Schema” namespace used for testing in the XML Resolver project: https://xmlresolver.org/ns/sample. It also contains a directory of links to these related resources, using Resource Directory Description Language.
The Sample Schema is a very simple documentation schema. In brief:
book
or an article
.
chapter
) or
articles (article
).title
) containing only text;
titles on articles are optional but, if present, contain only text.p
) which may
contain text and either emphasis (em
) or hypertext links (link
).
xlink:href
attribute.The Sample Schema is described with a DTD, XML Schema, and RELAX NG grammar.


// // Copyright (c) Microsoft and contributors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // // See the License for the specific language governing permissions and // limitations under the License. // // Module dependencies. var util = require('util'); var extend = require('extend'); var _ = require('underscore'); var azureCommon = require('./../../common/common'); var azureutil = azureCommon.util; var validate = azureCommon.validate; var SR = azureCommon.SR; var StorageServiceClient = azureCommon.StorageServiceClient; var SharedKeyTable = require('./internal/sharedkeytable'); var RequestHandler = require('./internal/requesthandler'); var TableQuery = require('./tablequery'); var WebResource = azureCommon.WebResource; var Constants = azureCommon.Constants; var QueryStringConstants = Constants.QueryStringConstants; var HeaderConstants = Constants.HeaderConstants; var TableConstants = Constants.TableConstants; var RequestLocationMode = Constants.RequestLocationMode; // Models requires var tableResult = require('./models/tableresult'); var entityResult = require('./models/entityresult'); var BatchResult = require('./models/batchresult'); var ServiceStatsParser = azureCommon.ServiceStatsParser; var AclResult = azureCommon.AclResult; var TableUtilities = require('./tableutilities'); /** * Creates a new TableService object. * If no connection string or storageaccount and storageaccesskey are provided, * the AZURE_STORAGE_CONNECTION_STRING or AZURE_STORAGE_ACCOUNT and AZURE_STORAGE_ACCESS_KEY environment variables will be used. * @class * The TableService object allows you to peform management operations with the Microsoft Azure Table Service. * The Table Service stores data in rows of key-value pairs. A table is composed of multiple rows, and each row * contains key-value pairs. There is no schema, so each row in a table may store a different set of keys. * * For more information on the Table Service, as well as task focused information on using it from a Node.js application, see * [How to Use the Table Service from Node.js](http://azure.microsoft.com/en-us/documentation/articles/storage-nodejs-how-to-use-table-storage/). * The following defaults can be set on the Table service. * defaultTimeoutIntervalInMs The default timeout interval, in milliseconds, to use for request made via the Table service. * defaultMaximumExecutionTimeInMs The default maximum execution time across all potential retries, for requests made via the Table service. * defaultLocationMode The default location mode for requests made via the Table service. * defaultPayloadFormat The default payload format for requests made via the Table service. * useNagleAlgorithm Determines whether the Nagle algorithm is used for requests made via the Table service.; true to use the * Nagle algorithm; otherwise, false. The default value is false. * @constructor * @extends {StorageServiceClient} * * @param {string} [storageAccountOrConnectionString] The storage account or the connection string. * @param {string} [storageAccessKey] The storage access key. * @param {string|object} [host] The host address. To define primary only, pass a string. * Otherwise 'host.primaryHost' defines the primary host and 'host.secondaryHost' defines the secondary host. * @param {string} [sasToken] The Shared Access Signature token. */ function TableService(storageAccountOrConnectionString, storageAccessKey, host, sasToken) { var storageServiceSettings = StorageServiceClient.getStorageSettings(storageAccountOrConnectionString, storageAccessKey, host, sasToken); TableService['super_'].call(this, storageServiceSettings._name, storageServiceSettings._key, storageServiceSettings._tableEndpoint, storageServiceSettings._usePathStyleUri, storageServiceSettings._sasToken); if (this.anonymous) { throw new Error(SR.ANONYMOUS_ACCESS_BLOBSERVICE_ONLY); } if(this.storageAccount && this.storageAccessKey) { this.storageCredentials = new SharedKeyTable(this.storageAccount, this.storageAccessKey, this.usePathStyleUri); } this.defaultPayloadFormat = TableUtilities.PayloadFormat.MINIMAL_METADATA; } util.inherits(TableService, StorageServiceClient); // Table service methods /** * Gets the service stats for a storage account’s Table service. * * @this {TableService} * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain the properties. * `response` will contain information related to this operation. */ TableService.prototype.getServiceStats = function (optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('getServiceStats', function (v) { v.callback(callback); }); var options = extend(true, {}, userOptions); options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY; var webResource = WebResource.get() .withQueryOption(QueryStringConstants.COMP, 'stats') .withQueryOption(QueryStringConstants.RESTYPE, 'service'); var processResponseCallback = function (responseObject, next) { responseObject.serviceStatsResult = null; if (!responseObject.error) { responseObject.serviceStatsResult = ServiceStatsParser.parse(responseObject.response.body.StorageServiceStats); } // function to be called after all filters var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.serviceStatsResult, returnObject.response); }; // call the first filter next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Gets the properties of a storage account’s Table service, including Azure Storage Analytics. * * @this {TableService} * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain the properties. * `response` will contain information related to this operation. * @return {undefined} */ TableService.prototype.getServiceProperties = function (optionsOrCallback, callback) { return this.getAccountServiceProperties(optionsOrCallback, callback); }; /** * Sets the properties of a storage account’s Table service, including Azure Storage Analytics. * You can also use this operation to set the default request version for all incoming requests that do not have a version specified. * * @this {TableService} * @param {object} serviceProperties The service properties. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} callback `error` will contain information if an error occurs; * `response` will contain information related to this operation. * @return {undefined} */ TableService.prototype.setServiceProperties = function (serviceProperties, optionsOrCallback, callback) { return this.setAccountServiceProperties(serviceProperties, optionsOrCallback, callback); }; /** * Lists a segment containing a collection of table items under the specified account. * * @this {TableService} * @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation. * @param {object} [options] The create options or callback function. * @param {int} [options.maxResults] Specifies the maximum number of tables to return per call to Azure ServiceClient. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {string} [options.payloadFormat] The payload format to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain `entries` and `continuationToken`. * `entries` gives a list of tables and the `continuationToken` is used for the next listing operation. * `response` will contain information related to this operation. * @return {undefined} */ TableService.prototype.listTablesSegmented = function (currentToken, optionsOrCallback, callback) { this.listTablesSegmentedWithPrefix(null /* prefix */, currentToken, optionsOrCallback, callback); }; /** * Lists a segment containing a collection of table items under the specified account. * * @this {TableService} * @param {string} prefix The prefix of the table name. * @param {object} currentToken A continuation token returned by a previous listing operation. Please use 'null' or 'undefined' if this is the first operation. * @param {object} [options] The create options or callback function. * @param {int} [options.maxResults] Specifies the maximum number of tables to return per call to Azure ServiceClient. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {string} [options.payloadFormat] The payload format to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain `entries` and `continuationToken`. * `entries` gives a list of tables and the `continuationToken` is used for the next listing operation. * `response` will contain information related to this operation. * @return {undefined} */ TableService.prototype.listTablesSegmentedWithPrefix = function (prefix, currentToken, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('listTables', function (v) { v.callback(callback); }); var options = extend(true, {}, userOptions); options.payloadFormat = options.payloadFormat || this.defaultPayloadFormat; var webResource = WebResource.get(TableConstants.TABLE_SERVICE_TABLE_NAME); RequestHandler.setTableRequestHeadersAndBody(webResource, null, options.payloadFormat); if(!azureutil.objectIsNull(currentToken)) { webResource.withQueryOption(TableConstants.NEXT_TABLE_NAME, currentToken.nextTableName); } if(!azureutil.objectIsNull(prefix)) { var query = new TableQuery() .where(TableConstants.TABLE_NAME + ' >= ?', prefix) .and(TableConstants.TABLE_NAME + ' < ?', prefix + '{'); webResource.withQueryOption(QueryStringConstants.FILTER, query.toQueryObject().$filter); } if(!azureutil.objectIsNull(options.maxResults)) { var query = new TableQuery().top(options.maxResults); webResource.withQueryOption(QueryStringConstants.TOP, query.toQueryObject().$top); } options.requestLocationMode = azureutil.getNextListingLocationMode(currentToken); var processResponseCallback = function (responseObject, next) { responseObject.listTablesResult = null; if (!responseObject.error) { responseObject.listTablesResult = { entries: null, continuationToken: null }; responseObject.listTablesResult.entries = tableResult.parse(responseObject.response); if (responseObject.response.headers[TableConstants.CONTINUATION_NEXT_TABLE_NAME] && !azureutil.objectIsEmpty(responseObject.response.headers[TableConstants.CONTINUATION_NEXT_TABLE_NAME])) { responseObject.listTablesResult.continuationToken = { nextTableName: null, targetLocation: null }; responseObject.listTablesResult.continuationToken.nextTableName = responseObject.response.headers[TableConstants.CONTINUATION_NEXT_TABLE_NAME]; responseObject.listTablesResult.continuationToken.targetLocation = responseObject.targetLocation; } } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.listTablesResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; // Table Methods /** * Gets the table's ACL. * * @this {TableService} * @param {string} table The table name. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain the ACL information for the table. * `response` will contain information related to this operation. */ TableService.prototype.getTableAcl = function (table, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('getTableAcl', function (v) { v.string(table, 'table'); v.tableNameIsValid(table); v.callback(callback); }); var options = extend(true, {}, userOptions); options.requestLocationMode = Constants.RequestLocationMode.PRIMARY_OR_SECONDARY; var webResource = WebResource.get(table) .withQueryOption(QueryStringConstants.COMP, 'acl'); var processResponseCallback = function (responseObject, next) { responseObject.tableResult = null; if (!responseObject.error) { responseObject.tableResult = tableResult.parse(responseObject.response, true); responseObject.tableResult.signedIdentifiers = AclResult.parse(responseObject.response.body); } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.tableResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Updates the table's ACL. * * @this {TableService} * @param {string} table The table name. * @param {object} signedIdentifiers The signed identifiers. Signed identifiers must be in an array. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain information for the table. * `response` will contain information related to this operation. */ TableService.prototype.setTableAcl = function (table, signedIdentifiers, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('setTableAcl', function (v) { v.string(table, 'table'); v.tableNameIsValid(table); v.callback(callback); }); var options = extend(true, {}, userOptions); var policies = null; if (signedIdentifiers) { if (!_.isArray(signedIdentifiers)) { throw new Error(SR.INVALID_SIGNED_IDENTIFIERS); } policies = AclResult.serialize(signedIdentifiers); } var webResource = WebResource.put(table) .withQueryOption(QueryStringConstants.COMP, 'acl') .withHeader(HeaderConstants.CONTENT_LENGTH, !azureutil.objectIsNull(policies) ? Buffer.byteLength(policies) : 0) .withBody(policies); var processResponseCallback = function (responseObject, next) { responseObject.tableResult = null; if (!responseObject.error) { // SetTableAcl doesn't actually return anything in the response responseObject.tableResult = {TableName : table}; if (signedIdentifiers) { responseObject.tableResult.signedIdentifiers = signedIdentifiers; } } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.tableResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, webResource.body, options, processResponseCallback); }; /** * Retrieves a shared access signature token. * * @this {TableService} * @param {string} table The table name. * @param {object} sharedAccessPolicy The shared access policy. * @param {string} [sharedAccessPolicy.Id] The signed identifier. * @param {object} [sharedAccessPolicy.AccessPolicy.Permissions] The permission type. * @param {date|string} [sharedAccessPolicy.AccessPolicy.Start] The time at which the Shared Access Signature becomes valid (The UTC value will be used). * @param {date|string} [sharedAccessPolicy.AccessPolicy.Expiry] The time at which the Shared Access Signature becomes expired (The UTC value will be used). * @param {string} [sharedAccessPolicy.AccessPolicy.IPAddressOrRange] An IP address or a range of IP addresses from which to accept requests. When specifying a range, note that the range is inclusive. * @param {string} [sharedAccessPolicy.AccessPolicy.Protocol] The protocol permitted for a request made with the account SAS. * Possible values are both HTTPS and HTTP (https,http) or HTTPS only (https). The default value is https,http. * @param {string} [sharedAccessPolicy.AccessPolicy.StartPk] The starting Partition Key for which the SAS will be valid. * @param {string} [sharedAccessPolicy.AccessPolicy.EndPk] The ending Partition Key for which the SAS will be valid. * @param {string} [sharedAccessPolicy.AccessPolicy.StartRk] The starting Row Key for which the SAS will be valid. * @param {string} [sharedAccessPolicy.AccessPolicy.EndRk] The ending Row Key for which the SAS will be valid. * @return {object} An object with the shared access signature. */ TableService.prototype.generateSharedAccessSignature = function (table, sharedAccessPolicy) { // check if the TableService is able to generate a shared access signature if (!this.storageCredentials || !this.storageCredentials.generateSignedQueryString) { throw new Error(SR.CANNOT_CREATE_SAS_WITHOUT_ACCOUNT_KEY); } validate.validateArgs('generateSharedAccessSignature', function (v) { v.string(table, 'table'); v.tableNameIsValid(table); v.object(sharedAccessPolicy, 'sharedAccessPolicy'); }); return this.storageCredentials.generateSignedQueryString(Constants.ServiceType.Table, table , sharedAccessPolicy, null, {tableName: table }); }; /** * Checks whether or not a table exists on the service. * * @this {TableService} * @param {string} table The table name. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain be true if the table exists, or false if the table does not exist. * `response` will contain information related to this operation. */ TableService.prototype.doesTableExist = function (table, optionsOrCallback, callback) { this._doesTableExist(table, false, optionsOrCallback, callback); }; /** * Creates a new table within a storage account. * * @this {TableService} * @param {string} table The table name. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain the new table information. * `response` will contain information related to this operation. * @return {undefined} */ TableService.prototype.createTable = function (table, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createTable', function (v) { v.string(table, 'table'); v.tableNameIsValid(table); v.callback(callback); }); var options = extend(true, {}, userOptions); var tableDescriptor = tableResult.serialize(table); var webResource = WebResource.post('Tables') .withHeader(HeaderConstants.PREFER, HeaderConstants.PREFER_NO_CONTENT); RequestHandler.setTableRequestHeadersAndBody(webResource, tableDescriptor); var processResponseCallback = function (responseObject, next) { responseObject.tableResponse = {}; responseObject.tableResponse.isSuccessful = responseObject.error ? false : true; responseObject.tableResponse.statusCode = responseObject.response.statusCode; if (!responseObject.error) { responseObject.tableResponse.TableName = table; } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.tableResponse, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, webResource.body, options, processResponseCallback); }; /** * Creates a new table within a storage account if it does not exists. * * @this {TableService} * @param {string} table The table name. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * `result` will be `true` if table was created, false otherwise * `response` will contain information related to this operation. * @return {undefined} * * @example * var azure = require('azure-storage'); * var tableService = azure.createTableService(); * tableService.createTableIfNotExists('tasktable', function(error) { * if(!error) { * // Table created or exists * } * }); */ TableService.prototype.createTableIfNotExists = function (table, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('createTableIfNotExists', function (v) { v.string(table, 'table'); v.tableNameIsValid(table); v.callback(callback); }); var options = extend(true, {}, userOptions); var self = this; self._doesTableExist(table, true, options, function(error, exists, response) { if (error) { callback(error, exists, response); } else if (exists) { callback(error, false, response); } else { self.createTable(table, options, function(createError, createResponse) { var created; if (!createError) { created = true; } else if (createError && createError.statusCode === Constants.HttpConstants.HttpResponseCodes.Conflict && createError.code === Constants.TableErrorCodeStrings.TABLE_ALREADY_EXISTS) { createError = null; created = false; createResponse.isSuccessful = true; } callback(createError, created, createResponse); }); } }); }; /** * Deletes a table from a storage account. * * @this {TableService} * @param {string} table The table name. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} callback `error` will contain information if an error occurs; * `response` will contain information related to this operation. * @return {undefined} */ TableService.prototype.deleteTable = function (table, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('deleteTable', function (v) { v.string(table, 'table'); v.tableNameIsValid(table); v.callback(callback); }); var options = extend(true, {}, userOptions); var webResource = WebResource.del('Tables(\'' + table + '\')'); RequestHandler.setTableRequestHeadersAndBody(webResource); var processResponseCallback = function (responseObject, next) { var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Deletes a table from a storage account, if it exists. * * @this {TableService} * @param {string} table The table name. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * `result` will be `true` if table was deleted, false otherwise * `response` will contain information related to this operation. * @return {undefined} */ TableService.prototype.deleteTableIfExists = function (table, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('deleteTableIfExists', function (v) { v.string(table, 'table'); v.tableNameIsValid(table); v.callback(callback); }); var options = extend(true, {}, userOptions); var self = this; self._doesTableExist(table, true, options, function(error, exists, response) { if (error) { callback(error, exists, response); } else if (!exists) { response.isSuccessful = true; callback(error, false, response); } else { self.deleteTable(table, options, function(deleteError, deleteResponse) { var deleted; if (!deleteError) { deleted = true; } else if (deleteError && deleteError.statusCode === Constants.HttpConstants.HttpResponseCodes.NotFound && deleteError.code === Constants.StorageErrorCodeStrings.RESOURCE_NOT_FOUND) { deleted = false; deleteError = null; deleteResponse.isSuccessful = true; } callback(deleteError, deleted, deleteResponse); }); } }); }; // Table Entity Methods /** * Queries data in a table. To retrieve a single entity by partition key and row key, use retrieve entity. * * @this {TableService} * @param {string} table The table name. * @param {TableQuery} tableQuery The query to perform. Use null, undefined, or new TableQuery() to get all of the entities in the table. * @param {object} currentToken A continuation token returned by a previous listing operation. * Please use 'null' or 'undefined' if this is the first operation. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {string} [options.payloadFormat] The payload format to use for the request. * @param {bool} [options.autoResolveProperties] If true, guess at all property types. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {Function(entity)} [options.entityResolver] The entity resolver. Given a single entity returned by the query, returns a modified object which is added to * the entities array. * @param {TableService~propertyResolver} [options.propertyResolver] The property resolver. Given the partition key, row key, property name, property value, * and the property Edm type if given by the service, returns the Edm type of the property. * @param {TableService~queryResponse} callback `error` will contain information if an error occurs; * otherwise `entities` will contain the entities returned by the query. * If more matching entities exist, and could not be returned, * `queryResultContinuation` will contain a continuation token that can be used * to retrieve the next set of results. * `response` will contain information related to this operation. * @return {undefined} * * The logic for returning entity types can get complicated. Here is the algorithm used: * ``` * var propertyType; * * if (propertyResovler) { // If the caller provides a propertyResolver in the options, use it * propertyType = propertyResolver(partitionKey, rowKey, propertyName, propertyValue, propertyTypeFromService); * } else if (propertyTypeFromService) { // If the service provides us a property type, use it. See below for an explanation of when this will and won't occur. * propertyType = propertyTypeFromService; * } else if (autoResolveProperties) { // If options.autoResolveProperties is set to true * if (javascript type is string) { // See below for an explanation of how and why autoResolveProperties works as it does. * propertyType = 'Edm.String'; * } else if (javascript type is boolean) { * propertyType = 'Edm.Boolean'; * } * } * * if (propertyType) { * // Set the property type on the property. * } else { * // Property gets no EdmType. * } * ``` * Notes: * * * The service only provides a type if JsonFullMetadata or JsonMinimalMetadata is used, and if the type is Int64, Guid, Binary, or DateTime. * * Explanation of autoResolveProperties: * * String gets correctly resolved to 'Edm.String'. * * Int64, Guid, Binary, and DateTime all get resolved to 'Edm.String.' This only happens if JsonNoMetadata is used (otherwise the service will provide the propertyType in a prior step). * * Boolean gets correctly resolved to 'Edm.Boolean'. * * For both Int32 and Double, no type information is returned, even in the case of autoResolveProperties = true. This is due to an * inability to distinguish between the two in certain cases. * * @example * var azure = require('azure-storage'); * var tableService = azure.createTableService(); * // tasktable should already exist and have entities * * // returns all entities in tasktable, and a continuation token for the next page of results if necessary * tableService.queryEntities('tasktable', null, null \/*currentToken*\/, function(error, result) { * if(!error) { * var entities = result.entities; * // do stuff with the returned entities if there are any * } * }); * * // returns field1 and field2 of the entities in tasktable, and a continuation token for the next page of results if necessary * var tableQuery = new TableQuery().select('field1', 'field2'); * tableService.queryEntities('tasktable', tableQuery, null \/*currentToken*\/, function(error, result) { * if(!error) { * var entities = result.entities; * // do stuff with the returned entities if there are any * } * }); */ TableService.prototype.queryEntities = function (table, tableQuery, currentToken, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('queryEntities', function (v) { v.string(table, 'table'); v.callback(callback); }); var options = extend(true, {}, userOptions); options.payloadFormat = options.payloadFormat || this.defaultPayloadFormat; var webResource = WebResource.get(table); RequestHandler.setTableRequestHeadersAndBody(webResource, null, options.payloadFormat); if (tableQuery) { var queryString = tableQuery.toQueryObject(); Object.keys(queryString).forEach(function (queryStringName) { webResource.withQueryOption(queryStringName, queryString[queryStringName]); }); } if(!azureutil.objectIsNull(currentToken)) { webResource.withQueryOption(TableConstants.NEXT_PARTITION_KEY, currentToken.nextPartitionKey); webResource.withQueryOption(TableConstants.NEXT_ROW_KEY, currentToken.nextRowKey); } options.requestLocationMode = azureutil.getNextListingLocationMode(currentToken); var processResponseCallback = function (responseObject, next) { responseObject.queryEntitiesResult = null; if (!responseObject.error) { responseObject.queryEntitiesResult = { entries: null, continuationToken: null }; // entries responseObject.queryEntitiesResult.entries = entityResult.parseQuery(responseObject.response, options.autoResolveProperties, options.propertyResolver, options.entityResolver); // continuation token var continuationToken = { nextPartitionKey: responseObject.response.headers[TableConstants.CONTINUATION_NEXT_PARTITION_KEY], nextRowKey: responseObject.response.headers[TableConstants.CONTINUATION_NEXT_ROW_KEY], targetLocation: responseObject.targetLocation }; if (!azureutil.IsNullOrEmptyOrUndefinedOrWhiteSpace(continuationToken.nextPartitionKey)) { responseObject.queryEntitiesResult.continuationToken = continuationToken; } } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.queryEntitiesResult, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Retrieves an entity from a table. * * @this {TableService} * @param {string} table The table name. * @param {string} partitionKey The partition key. * @param {string} rowKey The row key. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {string} [options.payloadFormat] The payload format to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {TableService~propertyResolver} [options.propertyResolver] The property resolver. Given the partition key, row key, property name, property value, * and the property Edm type if given by the service, returns the Edm type of the property. * @param {Function(entity)} [options.entityResolver] The entity resolver. Given the single entity returned by the query, returns a modified object. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will be the matching entity. * `response` will contain information related to this operation. * @return {undefined} * * @example * var azure = require('azure-storage'); * var tableService = azure.createTableService(); * tableService.retrieveEntity('tasktable', 'tasksSeattle', '1', function(error, serverEntity) { * if(!error) { * // Entity available in serverEntity variable * } * }); */ TableService.prototype.retrieveEntity = function (table, partitionKey, rowKey, optionsOrCallback, callback) { var entityDescriptor = { PartitionKey: {_: partitionKey, $: 'Edm.String'}, RowKey: {_: rowKey, $: 'Edm.String'}, }; validate.validateArgs('retrieveEntity', function (v) { v.stringAllowEmpty(partitionKey, 'partitionKey'); v.stringAllowEmpty(rowKey, 'rowKey'); }); this._performEntityOperation(TableConstants.Operations.RETRIEVE, table, entityDescriptor, optionsOrCallback, callback); }; /** * Inserts a new entity into a table. * * @this {TableService} * @param {string} table The table name. * @param {object} entityDescriptor The entity descriptor. * @param {object} [options] The request options. * @param {string} [options.echoContent] Whether or not to return the entity upon a successful insert. Default to false. * @param {string} [options.payloadFormat] The payload format to use in the response, if options.echoContent is true. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {TableService~propertyResolver} [options.propertyResolver] The property resolver. Only applied if echoContent is true. Given the partition key, row key, property name, * property value, and the property Edm type if given by the service, returns the Edm type of the property. * @param {Function(entity)} [options.entityResolver] The entity resolver. Only applied if echoContent is true. Given the single entity returned by the insert, returns * a modified object. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain the entity information. * `response` will contain information related to this operation. * @return {undefined} * * @example * var azure = require('azure-storage'); * var tableService = azure.createTableService(); * var task1 = { * PartitionKey : {'_': 'tasksSeattle', '$':'Edm.String'}, * RowKey: {'_': '1', '$':'Edm.String'}, * Description: {'_': 'Take out the trash', '$':'Edm.String'}, * DueDate: {'_': new Date(2011, 12, 14, 12), '$':'Edm.DateTime'} * }; * tableService.insertEntity('tasktable', task1, function(error) { * if(!error) { * // Entity inserted * } * }); */ TableService.prototype.insertEntity = function (table, entityDescriptor, optionsOrCallback, callback) { this._performEntityOperation(TableConstants.Operations.INSERT, table, entityDescriptor, optionsOrCallback, callback); }; /** * Inserts or updates a new entity into a table. * * @this {TableService} * @param {string} table The table name. * @param {object} entityDescriptor The entity descriptor. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain the entity information. * `response` will contain information related to this operation. * @return {undefined} */ TableService.prototype.insertOrReplaceEntity = function (table, entityDescriptor, optionsOrCallback, callback) { this._performEntityOperation(TableConstants.Operations.INSERT_OR_REPLACE, table, entityDescriptor, optionsOrCallback, callback); }; /** * Updates an existing entity within a table by replacing it. To update conditionally based on etag, set entity['.metadata']['etag']. * * @this {TableService} * @param {string} table The table name. * @param {object} entityDescriptor The entity descriptor. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain the entity information. * `response` will contain information related to this operation. * @return {undefined} */ TableService.prototype.updateEntity = function (table, entityDescriptor, optionsOrCallback, callback) { this._performEntityOperation(TableConstants.Operations.UPDATE, table, entityDescriptor, optionsOrCallback, callback); }; /** * Updates an existing entity within a table by merging new property values into the entity. To merge conditionally based on etag, set entity['.metadata']['etag']. * * @this {TableService} * @param {string} table The table name. * @param {object} entityDescriptor The entity descriptor. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain the entity information. * response` will contain information related to this operation. * @return {undefined} */ TableService.prototype.mergeEntity = function (table, entityDescriptor, optionsOrCallback, callback) { this._performEntityOperation(TableConstants.Operations.MERGE, table, entityDescriptor, optionsOrCallback, callback); }; /** * Inserts or updates an existing entity within a table by merging new property values into the entity. * * @this {TableService} * @param {string} table The table name. * @param {object} entityDescriptor The entity descriptor. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain the entity information. * `response` will contain information related to this operation. * @return {undefined} */ TableService.prototype.insertOrMergeEntity = function (table, entityDescriptor, optionsOrCallback, callback) { this._performEntityOperation(TableConstants.Operations.INSERT_OR_MERGE, table, entityDescriptor, optionsOrCallback, callback); }; /** * Deletes an entity within a table. To delete conditionally based on etag, set entity['.metadata']['etag']. * * @this {TableService} * @param {string} table The table name. * @param {object} entityDescriptor The entity descriptor. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResponse} callback `error` will contain information if an error occurs; * `response` will contain information related to this operation. * @return {undefined} */ TableService.prototype.deleteEntity = function (table, entityDescriptor, optionsOrCallback, callback) { this._performEntityOperation(TableConstants.Operations.DELETE, table, entityDescriptor, optionsOrCallback, callback); }; /** * Executes the operations in the batch. * * @this {TableService} * @param {string} table The table name. * @param {TableBatch} batch The table batch to execute. * @param {object} [options] The create options or callback function. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain responses for each operation executed in the batch; * `result.entity` will contain the entity information for each operation executed. * `result.response` will contain the response for each operations executed. * `response` will contain information related to this operation. * @return {undefined} */ TableService.prototype.executeBatch = function (table, batch, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('executeBatch', function (v) { v.string(table, 'table'); v.tableNameIsValid(table); v.object(batch, 'batch'); v.callback(callback); }); if(!batch.hasOperations()) { throw new Error(SR.EMPTY_BATCH); } var options = extend(true, {}, userOptions); var batchResult = new BatchResult(this, table, batch.operations); var webResource = batchResult.constructWebResource(); var body = batchResult.serialize(); webResource.withBody(body); webResource.withHeader(HeaderConstants.CONTENT_LENGTH, Buffer.byteLength(body, 'utf8')); var processResponseCallback = function (responseObject, next) { var responseObjects = batchResult.parse(responseObject); // if the batch was unsuccesful, there will be a single response indicating the error if (responseObjects && responseObjects.length > 0 && !responseObjects[0].response.isSuccessful) { responseObject = responseObjects[0]; } else { responseObject.operationResponses = responseObjects; } var finalCallback = function (returnObject) { // perform final callback callback(returnObject.error, returnObject.operationResponses, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, webResource.body, options, processResponseCallback); }; // Private methods /** * Checks whether or not a table exists on the service. * @ignore * * @this {TableService} * @param {string} table The table name. * @param {string} primaryOnly If true, the request will be executed against the primary storage location. * @param {object} [options] The request options. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `result` will contain be true if the table exists, or false if the table does not exist. * `response` will contain information related to this operation. */ TableService.prototype._doesTableExist = function (table, primaryOnly, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('doesTableExist', function (v) { v.string(table, 'table'); v.tableNameIsValid(table); v.callback(callback); }); var options = extend(true, {}, userOptions); if(primaryOnly === false) { options.requestLocationMode = RequestLocationMode.PRIMARY_OR_SECONDARY; } var webResource = WebResource.get('Tables(\'' + table + '\')'); RequestHandler.setTableRequestHeadersAndBody(webResource); var processResponseCallback = function (responseObject, next) { if(!responseObject.error){ responseObject.exists = true; } else if (responseObject.error && responseObject.error.statusCode === Constants.HttpConstants.HttpResponseCodes.NotFound) { responseObject.error = null; responseObject.exists = false; responseObject.response.isSuccessful = true; } var finalCallback = function (returnObject) { callback(returnObject.error, returnObject.exists, returnObject.response); }; next(responseObject, finalCallback); }; this.performRequest(webResource, null, options, processResponseCallback); }; /** * Peforms a table operation. * * @this {TableService} * @param {string} operation The operation to perform. * @param {string} table The table name. * @param {object} entityDescriptor The entity descriptor. * @param {object} [options] The create options or callback function. * @param {string} [options.echoContent] Whether or not to return the entity upon a successful insert. Default to false. * @param {string} [options.payloadFormat] The payload format to use for the request. * @param {LocationMode} [options.locationMode] Specifies the location mode used to decide which location the request should be sent to. * Please see StorageUtilities.LocationMode for the possible values. * @param {int} [options.timeoutIntervalInMs] The server timeout interval, in milliseconds, to use for the request. * @param {int} [options.maximumExecutionTimeInMs] The maximum execution time, in milliseconds, across all potential retries, to use when making this request. * The maximum execution time interval begins at the time that the client begins building the request. The maximum * execution time is checked intermittently while performing requests, and before executing retries. * @param {string} [options.clientRequestId] A string that represents the client request ID with a 1KB character limit. * @param {bool} [options.useNagleAlgorithm] Determines whether the Nagle algorithm is used; true to use the Nagle algorithm; otherwise, false. * The default value is false. * @param {errorOrResult} callback `error` will contain information if an error occurs; * otherwise `entity` will contain the entity information. * `response` will contain information related to this operation. * @return {undefined} * @ignore */ TableService.prototype._performEntityOperation = function (operation, table, entityDescriptor, optionsOrCallback, callback) { var userOptions; azureutil.normalizeArgs(optionsOrCallback, callback, function (o, c) { userOptions = o; callback = c; }); validate.validateArgs('entityOperation', function (v) { v.string(table, 'table'); v.tableNameIsValid(table); v.object(entityDescriptor, 'entityDescriptor'); v.object(entityDescriptor.PartitionKey, 'entityDescriptor.PartitionKey'); v.object(entityDescriptor.RowKey, 'entityDescriptor.RowKey'); v.stringAllowEmpty(entityDescriptor.PartitionKey._, 'entityDescriptor.PartitionKey._'); v.stringAllowEmpty(entityDescriptor.RowKey._, 'entityDescriptor.RowKey._'); v.callback(callback); }); var options = extend(true, {}, userOptions); options.payloadFormat = options.payloadFormat || this.defaultPayloadFormat; var webResource = RequestHandler.constructEntityWebResource(operation, table, entityDescriptor, options); var processResponseCallback = function (responseObject, next) { var finalCallback; if (operation === TableConstants.Operations.DELETE) { finalCallback = function (returnObject) { callback(returnObject.error, returnObject.response); }; } else { responseObject.entityResponse = null; if (!responseObject.error) { responseObject.entityResponse = entityResult.parseEntity(responseObject.response, options.autoResolveProperties, options.propertyResolver, options.entityResolver); } finalCallback = function (returnObject) { callback(returnObject.error, returnObject.entityResponse, returnObject.response); }; } next(responseObject, finalCallback); }; this.performRequest(webResource, webResource.body, options, processResponseCallback); }; /** * Given the partition key, row key, property name, property value, * and the property Edm type if given by the service, returns the Edm type of the property. * @typedef {function} TableService~propertyResolver * @param {object} pk The partition key. * @param {object} rk The row key. * @param {string} name The property name. * @param {object} value The property value. * @param {string} type The EDM type. */ /** * Returns entities matched by a query. * @callback TableService~queryResponse * @param {object} error If an error occurs, the error information. * @param {object} entities The entities returned by the query. * @param {object} queryResultContinuation If more matching entities exist, and could not be returned, * a continuation token that can be used to retrieve more results. * @param {object} response Information related to this operation. */ module.exports = TableService;