Friday, April 06, 2012

VIM Tip: Not Containing Pattern (2)

In my previous VIM tip blog, I mentioned about searching for a pattern of a expected word with not expected word afterwords, for example, 'tablespace' followed by a word not starting with 't'. When I tried to the pattern in an opposite way, I could not figure out how to do a match. For example, a word not starting with 't' followed by a word of 'tablespace'.

I think that I figure it out now, but it took me a while to google and digest the related information. I think it is worthwhile to study this. I am writing this blog to summarize my findings.

Lookahead and Lookbehand Zero-width Assertions


At first I thought about match a pattern not containing another pattern should be as simple as using a negate or ! operator to identify not-containing-pattern. There may be a not operator in VIM search, but I could not find it. What I found is Lookaround Zero-width Assertion.

In VIM, the way of search for a pattern not containing another pattern is very smart and elegant. The basic search is to find all matched patterns, and the matched items are returned as results. In VIM, the following is a search command:

/PATTERN

the pattern can be a regular expression.

In VIM, zero width pattern is a pattern to be matched but not in the search results. Think zero width pattern as additional match condition, it can be described as either of following ways:

PATTREN + ZERO_WIDTH_ATOM or
ZERO_WIDTH_ATOM + PATTERN

The first one is called as lookahead zero width assertion, and second one as lookbehind zero width assertion. Assertion here means matched or not matched. The above two are positive assertions. If we take negative or not matched into consideration, there are four types of look around with zero width assertions. They are:

/PATTERN[ZERO_WIDTH_ATOM\@=]
/PATTERN[ZERO_WIDTH_ATOM\@!]
/[ZERO_WIDTH_ATOM\@<=]PATTERN
/[ZERO_WIDTH_ATOM\@<!]PATTERN

Note: [...] is used as optional and also as separator from pattern, [ or ] are not part of search.

As my understanding, VIM uses symbolic like character for look around. As other special characters in VIM, \ is used to indicate look around with zero width assertion. The following table summarizes characters used for this type of search:

\@  indicate lookahead
\@<  lookbehind
=  positive match
!  negative or not match.

In above searches, PATTERN is to be matched. If ZERO_WIDTH_ATOM is supplied, it will be used as additional assertion. If there is any match, the matched pattern items will be returned as results, but ZERO_WIDTH_ATOM is not in the results. That's why it called as zero width.

According to VIM documentation, the definition of ATOM is a character, or a character class, or a group (indicated by \(...\) braces).

Think the Search as a Program


Lets think those type of searches as a program. Here I have the following c-style pseudo codes:

Results getMatchedResults(
   string context,               // basic
   string pattern,
   string zero_width_pattern,    // zero_width pattern
   bool match_zero_width_pattern,
   bool lookahead)
{
  results = EMPTY_LIST;
  result = getMatchedResult(context, pattern);
  while (result != EMPTY)
  {
    if (zero_pattern != EMPTY)
    {
      if ( lookahead ) {
        context_tmp = getNextContextByLookahead(context, result);
        result_tmp = getMatchedResult(context_tmp, zero_width_pattern);
      } else {
        context_tmp = getNextContextByLookbehind(context, result);
        result_tmp = getMatchedResultByLookbehind(context_tmp,
                       zero_width_pattern);
      }
      if ( result_tmp == EMPTY ) {
        if (match_zero_width_pattern) {
          result = EMPTY;
        }
      } else {
        if (!match_zero_width_pattern) {
          retult = EMPTY;
        }
      }
    }
    if ( result != EMPTY ) {
      results.add(result);
      context = geNextContextByLookahread(context, result);
      result = getMatchedResult(context, pattern);
    }
  }
  return results;
}

The pseudo codes are very straightforward. Actually, VIM search is based on Regex as its search engine. The above search expression commands are basic Regex patterns.


References


Read More...

Sunday, April 01, 2012

Steps to Delegate in iOS

I am back to the course of iOS Development by Stanford University. Last week, I watched Lesson 9 Table Views(October 25, 2011). Instructor Paul Hegarty mentioned 5 steps about Delegate at 1:04:15.

He talked the confusion for new developers when they use protocols.  The 5 steps are clear explanation on how to use and implement protocols. He also showed the steps in his demo.



  1. Create the @protocol
  2. Add delegate @property to delegator's public @interface
  3. Use delegate property inside delegator's implementation
  4. Set the delegate property somewhere inside the delegate's @implmentation
  5. Implement the protocol's method(s) in the delegate(include <> on @interface)


In the demo, the protocol CalculatorProgramsTableViewControllerDelegate is created in CalculatorProgramsTableViewController.h:

@class CalculatorProgramsTableViewController;

@protocol CalculatorProgramsTableViewControllerDelegate

@optional
- (void)calculatorProgramsTableViewController:(CalculatorPorgramTableViewController *)sender
                                 choseProgram:(id)program;
@end

In CalculatorProgramsTableViewController.h, the delegate is created in the controller as weak id <...> delegate:

@interface CalculatorProgramsTableViewController : UITableViewController
...
// Define a property delegate
@property (nonatomic, weak) id<CalculatorProgramsTableViewControlerDelegate> delegate;
...
@end

In its .m file, the delegate property is defined by @synthesize delegate = _delegate.

@implementation CalculatorProgramsTableViewController
...
@synthesize delegate = _delegate;
...
@end

In the event of a row cell being selected, the delegate is used:

#progma mark - UITableViewDelegate

- (void)tableView:(UITableView *)tableView
    didSeelectRowAtIndexPath:(NSIndexPath *)indexPath
{
  id program = [self.programs objectAtIndex:indexPath.row];
  [self.delegate calculatorProgramsTableViewController:self
                                          choseProgram:porgram];
}

Next, where the delegate is set? in the event of controller segue. The delegate method is implemented in the controller:

@implementation CalculatorGraphViewController
...
- (void)prepareForSegue:(UIStoryboardSegue *)segue
                 sender:(id)sender
{
  if ([segue.identifier isEqualToString:@"Show Favorite Graphics"]) {
    NSArray * programs = [[NSUserDefaults standardUserDefaults]
      objectForKey:FAVORITES_KEY];
    [segue.destinationViewController setPrograms:programs];
    [segue.destinationViewController setDelegate:self]; // set delegate
  }
}

Lastly, in order for the graphic view controller to know the change of a program, the controller has to implement the delegate method. The protocol method will be called when the delegate sends out its message: a row in table view being selected:

// in .h file, the protocal delegate is defined as the controller's interface
@interface CalculatorGraphViewController : NSOjbect
             <CalculatorProgramsTableViewControllerDelegate>
...
@end

//In .m The protocol method is implemented
- (void)calculatorProgramsTableViewController:(CalculatorProgramsTableViewController *)sender
                                chooseProgram:(id)program
{
  self.calculatorProgram = program;
}

"That's all we need. OK!", Paul said.

References


Read More...

Saturday, March 24, 2012

VIM Tip: Not Containing Pattern (1)

Here is one tip I used last week when I tried to use VIM to match strings with a pattern not containing a pattern. The requirement is about a group of PL/SQL scripts. I have to update some lines in the script containing "tablespace xxx", where xxx is a table space name. There is one exception: don't change "tablespace temp".

I decided to use VIM Search and Replace feature to do the job. Since my search is case insensitive, first, I use the following command to tell VIM to ignore case for my search:

:set ignorecase

Then I used the following search pattern:

/tablesapce\s\+\(t\w\+\)\@!

This search is for any line containing word "tablespace" following any spaces, but the following word  beginning with "t". The following table explains some special characters in VIM:

ItemDescription
\swhitespace character
\+matches 1 or more of the preceding characters...
\(...\)enclosing a pattern as a group.
\wwork character
\@!not containing
\nthe matched pattern in the n pair of \(\), for example, \1 for the first matched group \(\).

Here I used group pattern with containing trick "\@!", which means that the word in the group does not  contain a word beginning with "t".  In my case, "tmp" is an example.

After I verified that the search result meets my requirement. The replace is used:

%s/\(tablespace\s\+\)\(t\w\+\)\@!/\1MyTablespace/gi

\1 is the matched the group 1, i.e., "tablespace" plus white space. Here gi means global and ignore case.

Read More...

Saturday, March 17, 2012

Add Wolfram|Alpha Query Box in Blog

I have spent some time on WolframAlfram(WA) computable knowledge engine during evenings recently. What I found is that all Wolfram products, projects or apps are based on Mathemetica software or application. For example, WA, CDF(computable document format), and Mobile apps.

From WA web page, I find a link about how to add WA to blog or web sites. The HTML script is very simple one. There are serval sizes available. Here is an example to add a small size WA:

1 <script id="WolframAlphaScript" 
2   src="http://www.wolframalpha.com/input/embed/?type=medium"
3   type="text/javascript">
4 </script>

Here is what it looks like:

However, I could not find a way to put a query text into the WA input box directly. In WA, you can type a query text there, for example, pi. From there, I can get a URL about the query:

http://www.wolframalpha.com/input/?i=pi

As a result, an alternative way to add a WA query is to add a link with a query text:

Query: pi



References

Read More...

Saturday, March 10, 2012

CodeRetreat and Corey Haines

On my way home from work, I listened to Hansleminutes podcast on 3/1/2012. The podcast was a talk with Corey Haines. By the end when Hansel mentioned about Corey's coding and boarding experience, I immediately recalled the Corey! He is the man who was on .Net Rocks talk several years ago. Since then I followed him on Twitter.

His story impressed me. That's quite adventure way to update development skills. After I left his job in 2009, he started his one-year journey cross US, pair programming for a room and board. He mentioned in the .Net Rocks interview that he mention various people, include some gurus. I think that that year he learned a lot. Just like in his web page, he was like "a bee" to suck knowledge and development skills from people. Even at times he was working with people at the same or less level as him, he still practiced his presentation and personal skills. I think he was single at the that time.

I sent him a tweet to ask if he was the person on the .Net Rock podcast after the talk. I have never got his reply. That's OK. I knew that was him. Since then(by the end of 2009), I have not heard anything about him.

It was a refreshing news when I heard him again on Hanselminutes. This time, Corey talked about his project of code retreat. Basically, it is a kind intensive training, one whole day. A group of people repeat about 5 rounds of 45 minute pair programming focusing one specific problem. I really like this kind of project. I joined his coderereat organization on the same day after the podcast (in the evening).

I think that the project of coderetreat is a continuing and extension of his journeyman of programming. The journeyman was just one-to-one experience. Now he extends it to group of people.

In addition to his talk about coderettreat project, I found that he has been actively providing consulting services, talks, and some projects. In his web page, there are two web-based projects: MercuryApp and Slottd. MercuryApp provides a tracking service for any thing. Basically you score your feeling about project, word, thing or anything else. If you keep entering scores over a period of time, you may gain a view over the item you have tracked. You need to create an account with your email.



Slottd is a simple scheduler web service. You don't need an account to use. However, you do need to provide an email for your to update your schedule later one. For example, I created one meeting for the next Monday with 2 spots available. After the schedule is created, you will get two temporary URLs by email: one for update and another one for people to take the spot. It is a simple idea and quite useful. I think that this service might be a result of their code retreat projects.



All those web services are simple ones, but they are great examples to work together. Within a short period of time,  a team work on the project in Agile. Every one will learn from it by hands-on-codeing.

Another developer who has great impact on programming skills and my life is Jean-Paul Sylvain Boodhoo. When I was working as a consultant at Bantrel, JP was invited to provide one week training on .Net with TDD. That was great training. Even during the day I had to work(no contractors were invited for free), I went to the training session after work 5:00pm immediately. He was so passionate with the training. He should finish by 5:00PM, but he just went to late 9:00PM, even 11:00PM. That experience fired my up. Since then I started to keep my skills update to date with my passion.

Not sure if there are any one in Calgary area like to form a similar project. The start may have just couple of developers. This kind of activity will tremendously benefit development skills for sure.

References



Read More...

Thursday, March 08, 2012

More on XSLT Transformation

In my previous blog, I described how I used XSLT transformation to convert XML content to HTML content. That one is a very simple example. This technique is not very commonly used but I think it is very useful. As I mentioned that I used the same technique more than 10 years ago. Here I add more on this issue for my personal references.

The previous example is based on an XML file from my SQL Server Profiler tracing result: I want to convert all the interested Column nodes under Event into a HTML table. Last week, I realized that all those events can be further divided into three SQL groups based on SQL calls: Current, Data and TagInfo. It would be nice if I could create three HTML tables to summarize those results. I spent some time to explore more on XSLT transformation. The following are some related transformation elements I used.

XSL Variables


In XSL, variables can be defined for reuse. I need three HTML tables. Each has the same headers and footers. I found that by defining variables, it is a very neat strategy to create my HTML tables with constant herder and footer.

  <xsl:variable name="header">
    <tr bgcolor="#9acd32">
      <th>Row index</th>
      <th>CPU</th>
      <th>Reads</th>
      <th>Duration</th>
      <th>Writes</th>
    </tr>
  </xsl:variable>
  <xsl:variable name="footer">
    <tr bgcolor="#9acd32">
      <th>Total</th>
      <th></th>
      <th></th>
      <th></th>
      <th></th>
    </tr>
  </xsl:variable>

Here are variables: header and footer, each corresponding to HTML table header and footer sections.

In the next section, you will see how those variables are used.

One limitation of XSLT variables is that they are immutable. That means you cannot change value after a variable is defined or created. I would like to have some variables to sum all CPU, Reads, Duration values, but I could not figure out how. My solution is to copy my HMLT table results and paste them to Excel to do the calculation.

XSLT If Element


I used XSLT If element as a predicate for my HMTL table content:

<table border="1">
  <xsl:copy-of select="$header"></xsl:copy-of>
  <xsl:for-each select="TraceData/Events/Event[@name='SQL:BatchCompleted']">
    <xsl:if test="starts-with(Column[@name='TextData'], 'EXEC sp_PVSQL_Template_MANUAL_Data')">
      <tr>
        <td>
          <xsl:value-of select="position()" />
        </td>
        <td>
          <xsl:value-of select="Column[@name='CPU']" />
        </td>
        <td>
          <xsl:value-of select="Column[@name='Reads']" />
        </td>
        <td>
          <xsl:value-of select="Column[@name='Duration']" />
        </td>
        <td>
          <xsl:value-of select="Column[@name='Writes']" />
        </td>
      </tr>
    </xsl:if>
  </xsl:for-each>
  <xsl:copy-of select="$footer"></xsl:copy-of>
</table>

The above codes also show the usage of my XSLT variables for my HTML header and footer sections.

XSLT Functions


In above codes, I used an XSLT function in XSLT If test: starts_with(a, b). This is a useful string function to check if string a starts with b string, case sensitive. The function of position() is used to get XML Row index, which is a reference node position in the original XML content.

However, the parameters of the function have to be in the correct case, case sensitive. I tried to use lower_case() and match() function. Unfortunately, those functions are only available in XSLT 2.0. The tool of XML Notepad does not support XSLT 2.0, nor I can find updates for the tool.

References


Read More...

Sunday, February 26, 2012

Using XSLT and XPath to Transform XML

I remember that I did this kind transformation about 10 years ago, by using XSLT and XPath to transform an XML file to a HTML file. Last week I was working on tracing files generated by SQL Server Profiler tool. The tracing information can be saved as XML file as well. This XML file contains information in a structure like a database table: a long list of events, each event like a row of data with multiple columns.

What I was interested are columns of CPU, Reads, Writes and Duration. I need to convert those information into a HTML format so that I can copy and paste them to Excel. I could use PowerShell, Javascript, write .Net program to do the job, but I decided to recall my previous skills. This has been great experience for me. The following are the main steps.

XML File


The XML file is the source of data.  In my example case, I used SQL Server Profiler tool to get data communication from an application to a SQL server. All those information are recorded as data of events.



The SQL Server Profile provides a way to save the result to XML file:



I opened the XML file in notepad. The columns of CPU, Reads, Writes, and Durations are in a node of Event with attribute name="SQL:BatchCompleted". The path of Event is TracedData\Events\Event. Under the Event node, there is collection of Column nodes.  Each Column has an attribute name as its identity, and my interested Column nodes are name="CPU", "Reads", "Writes" and "Durations".

Using XSLT and XPath


Last time I learned XLST and XPath were at W3Schools.  The information are still there. XLST is the basic tool to do a transformation. Within the XLST, XPath is used to search for or match XML nodes.

My purpose is to extract some XML nodes and present their values into a HTML table format. This is my XSL file:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
<html>
  <body>
    <form method="post" action="edittool.asp">
    <h2>SQL Server Profiler Result</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th>CPU</th>
        <th>Reads</th>
        <th>Duration</th>
        <th>Writes</th>
      </tr>
      <xsl:for-each select="TraceData/Events/Event[@name='SQL:BatchCompleted']">
      <tr>
        <td>
          <xsl:value-of select="Column[@name='CPU']"/>
        </td>
        <td>
          <xsl:value-of select="Column[@name='Reads']"/>
        </td>
        <td>
          <xsl:value-of select="Column[@name='Duration']"/>
        </td>
        <td>
          <xsl:value-of select="Column[@name='Writes']"/>
        </td>
      </tr>
      </xsl:for-each>
    </table>
  </form>
  </body>
</html>
</xsl:template>
</xsl:stylesheet>

To get all the nodes of Event with attribute name="SQL:BatchCompleted", I use XSL:for-each select syntax to loop the collection. Then I use XSL:value-of to get Column node's value. To specify CPU Column, I used XPath Predicate [@attributename...] syntax. For example, Column[@name='CPU'] is to specify Column node with attribute name with 'CPU' value.

Using Browser to View Results


What I like to do the transformation is simply using a browser, dragging XML file to a browser to display results as HTML content. I don't like to put XML and XSLT to a web server to get the same result.

Add a line to XML to specify XLST transformation at the beginning:

<?xml version="1.0" encoding="utf-16"?>
<?xml-stylesheet type="text/xsl" href="cdcatalog.xsl"?>

This line will add a link of an XSL style sheet to an XML document.

To my surprise, I saw no result in Chrome. The content was blank! By enabling Inspect Element form browser's context menu, I found that actually this was a security issue:




Soon I found that this could be resolved by disabling web-security. I created a shortcut of Chrome and added command line argument of -disable-web-security.



You have to close all the current Chrome instances before launching this one. With this command option, my XML was then transformed and displayed in Chrome browser.



10 years ago, I was using IE to display the transformation. IE still works fine today. I think this makes sense. The URL of the XML file is actually local file: file:///E:.... The link in XML to a XSL file should be able accessible locally in browser.



XML NotePad Tool


I have a favorite tool for viewing XML file: XML Notepad. During the time I was using browser to view transformed XML file, I found that XML Notepad has a build in function to do that.



In the second tab, XML Output, I realized that it let use to choose a XSL file to transform the XML file.



The another advantage is that there is no need to embed a link to XSL file.

References


Read More...

Friday, February 17, 2012

Some Views Cannot be Matertialized

In the past weeks, I was asked to work on improving SQL server performance for a client application.  Basically, the application have some SQL template settings for retrieving data from SQL server databases.  I did this kind job last year. What I did was using materialized views, i.e., views cache static data if they are not changed.

However, this time I could not make my updated views as materialized ones. After further analysis, I realize that this is not SQL's fault. If a view has some dynamic components, such as columns, the view just cannot cache data. In this sense, the view cannot be materialized.

For the following SQL SELECT is one example:

SELECT ID, CAST(@StartDate + ' ' + @StartTime AS DATETIME) AS DT, VALUE
FROM MyTable;

Since the column DT is dynamically built by two variables, SQL server just cannot cache data.

My assignment actually is much more complicated than this case. The strategy I worked out was to stand back first. I tried to understand the application SQL templates. What kind of data are queried? Based on my understanding, I tried to create a set of database tables to meet the requirement.  Then I added triggers to source data tables to populate data from the source to the new tables. As a result, the views as SQL templates were much easy to build.

What I learned from this project is that you cannot always implement one strategy to solve all the problems, even though the implementation strategy has been successfully used before. If it is too hard to use the same strategy, you have to stand back, re-think the issue in a wide prospective view, and try to take alternative path. This may actually lead to find another good solution.

Read More...

Sunday, February 12, 2012

Web service: Wolfram|Alpha

I was suppressed to know the web service of Wolfram|Alpha, a computable knowledge engine. I knew this one by aan article of AppleInsider about 1/4 Siri searching result from Wolfram|Alpha.

Unlike the search by Google, the results are collection of web pages or resources based on a query's relevance or top hits. The inventor Stephen Wolfram said that Wolfram|Alpha is not a search engine. Instead, it is a computable knowledge engine which provides results from its back-end computer system, Methematica, with curated data.

After the initial discovery, I was fascinated with this idea of combining math, computer program, data and systematic experiments. For me this is a new idea, but Stephen has spent his 30 year research on this.  At the time I found this service, Wolfram|Alpha was in the trial stage and soon two days ago the Pro is out.

Based on the information, the structure of this web service is composed of four basic blocks:


Since the results are computed and presented as a list of graphics, tables, and explanations, there are no source information. In this sense, this web service is not a replacement for Google server, but a quite nice complement.  I have tried to search for some code solutions but with no actually any results. I hope the future version may provide nice solutions as well.

References

Read More...

Saturday, February 04, 2012

How to create a login page using ASP.NET MVC 3 Razor

I am back to MVC project. I used MVC for web application long time ago when it was still in Microsoft Patterns & Practice development. Now it is part of .Net 3.5 and 4.0 framework and all the classes and templates are available in Visual Studio 2011.

I need to add a Login page to my project. The way I did in my ASP.Net is quite different from the way in MVC. Since MVC has been changed a lot in terms of structure and framework, I have to learn MVC again. The MVC templates created by Visual Studio 2010 do not have Login feature. Fortunately, I found this tutorial on Youtube in short time:

The tutorial example is what I want.  It seems very easy to add Login page to MVC project.

First, add restriction in web.config file with Location element:

<configuration>
   <location path="">
      <system.web>
         <authorization>
            <deny users="?"/>
         </authorization>
      </system.web>
   </location>
</configuration>

The above will disable access to all the pages in the site.  Then add authentication element for login page in web.config:

<authentication mode="Forms">
  <forms loginUrl="~/Login/Login.aspx" timeout="120" />
</authentication>

In order to ensure the authentication in other web pages, a cooky is added before redirect to other forms on server side, as an indication been authenticated (part 3):

FormsAuthendication.SetAuthCookies(key, persistent);

In the place where log out is implemented, the following code is used to clear the cookie (part 4):

FormsAuthendication.SignOut();

That's all the basics.

In addition to those steps, the tutorial explains master page in MVC, which is in the Views->Shared folder. Different master pages can be specified (part 4). One interesting thing in MVC is that cs and html are all in one source code file as cshtml extension.

The tutorial also explains some very basic concepts in MVC:
  • Router structure in Global.assax (part 1)
  • Model for a view (part 5)
  • Get and Post actions mapping to View's methods

Read More...

Saturday, January 28, 2012

iOS Training Cource by Stanford University

I wrote the following blog while I was in Wuhan, China, during my vacation. For some reason, I could not access to my blogger there. I had to write my blogs in my sina blog. Now I copy the blog back to my programming blog.


I had to write my English blog at Sina blog web site since the Blogger is not accessible, during my visit to my extended family in Beijing and Wuhan. Fortunately, I have a Sina blog account so that I can continue to write my blog. I'll copy this blog to my Blogger when I get back.

Before I left for China, I found that iOS training by Stanford University(SU) was released. This is fall session course, started being published in Nov 2012. SU started to provide iPhone training courses several years ago, and I watched all the past iPhone training courses. I enjoy watching those courses very much. Even the course is an entry program for developers about iPhone application and Objective-C, the content has been kept up with the update of iOS. Based on the techniques and knowledge I learned from the course, I started my iPhone application development. I have to say that SU's course helps me a lot.

I think that SU's training course was one of a few educational programs for iPhone development and Obective-C. I greatly appreciate the updated content of the course along with the iOS progress. This time, the SU's iOS course has so many new contents about iOS 5. This course is quite different from the previous ones. For example, there is no more memory management by keeping track of reference counts. The XCODE is based on the new version of XCODE 4. The storyboard is included in the course as well. I think this course is a must-watch program for every iPhone and iPad developer.

I like the instructor, Paul Hegarty, very much. He started to teach this course last year. In this training, during the date Steve Jobs passed away, he revealed that he was in part of Steve Jobs' NeXT computer team in the early years. Later on he moved to University to teach computer courses. He is very knowledgable in Mac and iOS development.

I have downloaded all available classes before my leave from iTunes U. Now (Jan 7, 2012) I finished about 7 classes.

It seems that all those courses are available in iTunes U in China. The iTunes U course is in two formats: one in SD and another in HD. There is big difference in size. HD, in hight definition, takes a lot of spaces and thence takes too long time to download. For me, it is just a course to learn new things, and most likely I would not watch it again. Therefore, I would recommend to download the SD serials instead. Search for "iPhone" in iTunes to find SD serials.



References


Read More...

Sunday, January 15, 2012

Two ASP.Net Tips

I will be on vacation to China and be back on Jan 15, 2012. Since the Blogger is not accessible from China, I have to schedule my blog so that I will keep my promise to write at least one blog per week. This blog is a scheduled post.

This is note on two tips I found in ASP.Net.

Bind Field with Object Method


It is very common to bind a field to an object's property value. However, I find out one case that I prefer to bind a field with the object's method. The advantage of binding to a method is that I can pass parameter values in. I found a solution from SO.

Here is my example:

<asp:RequiredFieldValidator 
ID="RequiredFieldValidator1" 
runat="server" 
ControlToValidate="txtValue1"
Visible='<%#((MyData) Container.DataItem).RawValueAvailable(1) %>'
ErrorMessage="Value cannot be empty">*
</asp:RequiredFieldValidator>

I need to add required validation control with a condition if there is value for the bound object.  The above example sets Visible with the method "RawValueAvailable(..) of the bound object of MyData.  It works great.

Set Login Timeout


By default ASP.Net authentication has a timeout of 30 minutes. This timeout looks like that it can be customized. I found an answer from SO. Here is an example:

<system.web>
  <authenticationmode="Forms">
    <formstimeout="50"/>
  </authentication>
  <sessionStatetimeout="60"  />
</system.web>

Setting the forms timeout to something less than the session timeout can give the user a window in which to log back in without losing any session data. However, I think that client side cached data will be gone if redirect is called. For example, if a user enters several data into a data grid view, the changed data may be lost if login timeout is passed. There may be a way to provide warning for saving data by using Javascripts.

References

Read More...

Tuesday, January 03, 2012

Interesting Discovery of float.Parse()

I found some thing really interesting about float.Parse() method. Normally, I thought this parse method should be able to convert any numeric string to a float value, as long as it does not cause overflow. However, I found that it does not really faithfully do the conversion. If the string value is too small or too big, you may lost some precision in value.

Here I tried to narrow down this issue to a test program:

private static void TestFloat() {
  for (int index = 1; index &lt; 10; index++)
  {
      string val = string.Format("{0}.123456", new string('8', index));
      float f = float.Parse(val);
      string sF = f.ToString();
      string sF1 = f.ToString("0.000000");
      Console.WriteLine(@"string value: {0}(len: {5}); float value: {1}(len: {6}-{7});
string to float.Tostring()    {0}=={1}? {3};
string to float.Tostring(xxx) {0}=={2}? {4}",
       val, f, sF1, val.Equals(sF), val.Equals(sF1), val.Length, sF.Length, sF1.Length);
  }
}

The result is very surprising:


string value: 8.123456(len: 8); float value: 8.123456(len: 8-8);
  string to float.Tostring()    8.123456==8.123456? True;
  string to float.Tostring(xxx) 8.123456==8.123456? True
string value: 88.123456(len: 9); float value: 88.12346(len: 8-9);
  string to float.Tostring()    88.123456==88.12346? False;
  string to float.Tostring(xxx) 88.123456==88.123460? False
string value: 888.123456(len: 10); float value: 888.1235(len: 8-10);
  string to float.Tostring()    888.123456==888.1235? False;
  string to float.Tostring(xxx) 888.123456==888.123500? False
string value: 8888.123456(len: 11); float value: 8888.123(len: 8-11);
  string to float.Tostring()    8888.123456==8888.123? False;
  string to float.Tostring(xxx) 8888.123456==8888.123000? False
string value: 88888.123456(len: 12); float value: 88888.13(len: 8-12);
  string to float.Tostring()    88888.123456==88888.13? False;
  string to float.Tostring(xxx) 88888.123456==88888.130000? False
string value: 888888.123456(len: 13); float value: 888888.1(len: 8-13);
  string to float.Tostring()    888888.123456==888888.1? False;
  string to float.Tostring(xxx) 888888.123456==888888.100000? False
string value: 8888888.123456(len: 14); float value: 8888888(len: 7-14);
  string to float.Tostring()    8888888.123456==8888888? False;
  string to float.Tostring(xxx) 8888888.123456==8888888.000000? False
string value: 88888888.123456(len: 15); float value: 8.888889E+07(len: 12-15);
  string to float.Tostring()    88888888.123456==8.888889E+07? False;
  string to float.Tostring(xxx) 88888888.123456==88888890.000000? False
string value: 888888888.123456(len: 16); float value: 8.888889E+08(len: 12-16);
  string to float.Tostring()    888888888.123456==8.888889E+08? False;
  string to float.Tostring(xxx) 888888888.123456==888888900.000000? False

To my discovery, the parsed result lost its precision, 9 out of 10!

I found this issue when I tried to take an input string from a text box, convert it to a float value and finally save to database.  My tester found that the results are not consistent when value is too big. At the beginning I did not believe it, but after I repeated the case, I found the bizarre result.  Finally I realized the issue is caused by Parse() method.

Any way to get around this issue? It seems there is no way to save the exactly value to database. Even I can save the value as a string to database, eventually, it may reach a point that database will present the value as xxxEzz format, which may lost precision when the value is retrieved back.

It looks like that we have to limit values to be entered, to a realistic range. Then handle the value from UI to database or vice visa.


This blog is published by schedule.

Read More...

Sunday, January 01, 2012

Tips for Better 2012

This is a scheduled post. I got the following tips from my friend in a PPS show. I like it very much. Instead of chaining the email to others, here I put it in my blog.

Tips for the better life for 2012


  • Take a 10-30 minutes walk every day and while you walk, smile.
  • Sit in silence for at least 10 minutes each day.
  • Sleep for 7 hours
  • Live with the 3E's Energy, Enthusiasm, and Empathy.
  • Play for more games.
  • Read more books than you did in 2011.
  • Drink plenty of water
  • Eat more foods that grow on trees and plants and eat less food that is manufactured in plants.
  • Eat breakfast like a king, lunch like a prince, and dinner like a beggar.
  • Make time to practice meditation, yoga, and prayer. They provides us with daily fuel for our busy lives.
  • Dream more while you are awake.
  • Smile and laugh more.
  • Try to make at least three people smile each day.
  • Don't waste your previous energy on gossip.
  • Don't have negative thoughts or things you cannot control. Instead invest your energy in the positive present moment.
  • Spend time with people over the age of 70 & under the age of 6.
  • Life is too short to waste time hating anyone. Don't hate others.
  • Don't take yourself so seriously. No one else does.
  • Forget issues of the past. Don't remind your partner with his/her mistakes of the past. That will ruin your present happiness.
  • Realize that life is a school and you are here to learn. Problems are simply part of the curriculum that appear and fade away like algebra class, but the lessons you learn will last a lifetime.
  • You don't have to win every argument. Agree to disagree.
  • Don't compare your life to others'. You have no idea what their journey is all about. Don't compare your partner with others.
  • Make peace with your past so it won't spoil the present.
  • Your job won't take care of you when you are sick. Your friends will. Stay in touch.
  • Forgive everyone for everything.
  • What other people think of you is none of your business.
  • However good or bad a situation is, it will change.
  • Get rid of anything that isn't useful, beautiful or joyful.
  • Envy is a waste of time. You already have all you need.
  • The best is yet to come.
  • No matter how you feel, get up, dress up and show up.
  • Don't over do. Keep your limits.
  • Your inner most is always happy. So be happy.
  • Do the right thing!
  • Call your family often.
  • Each day give something good to others.
Please, forward this to everyone you care about.

Read More...

Sunday, December 25, 2011

Great Year 2011, and Welcome to 2012

It is time to close to the end of Year 2011.  At the time this blog is published, I am on my way to China to visit my mother, sister and brother.

This is another great year for me. I finished my contact for 2011 at Husky Energy and I'll move to development team for another year.  Even though I have done not much programming this year, I have learned so much by provide application support.  This has been great experience to learn much more about applications, by using application, trouble shooting issues, and providing helps to gain better understanding of applications created by other people and companies.

I think to extend knowledge to a wide range is very important. You will never know when those skills and knowledge will be useful.  My past experiences with a wide range of stuff benefit so much.  This has been proved in my work in 2011.  In so many cases, my past knowledge in SQL, Oracle, OPC, Windows System, programming knowledge in .Net, UNIX, even VI has helped me  a lot. Never stop learning and never say no something you don't know. Face the challenge and invest your time and effort, as well as keeping the habit to learn something new.  All those inputs will bring great results in long run for sure.

My Apple development has no progress at all in 2011; however, I did spend time to finish all the WWDC videos.  The reason I don't have time on iOS app development is that I just don't have time.  I have changed my focus in another none-programming area and put a lots of my time and effort on my Chinese blog.  This is another sharing experience and I think it is important for me to do.  In this area, I have set up a solid and great start up.  When I settle down in this area, I'll go back my iOS and Mac app development. Actually, I will find some interesting and great potential topics to work on.

My next year contract will be also full of challenges and new opportunities.  In the past month I have been working on an ASP.Net project based on .Net framework 2.0.  The next version will be on .Net 4.0 with MVC, and Infragistics tools.  I am exited and looking forward to taking the challenge.

However, I think my .Net knowledge and skills are up to the comfort level for me to stay for a while. My next territory will be in Apple's iOS and Mac. I have laid solid foundation.  I'll continue to head in to the new area with passion.

As always, this blog will my sharing land to mature my programming experiences. It'll be very valuable to overview my trace in the feature. Let me leave my deep and clear foot prints. I'm sure it will enjoyable time to read myself.

Read More...

Sunday, December 18, 2011

Using LDAP to Authenticate Windows Users

Here are some my programming notes about using LDAP library to authenticate Windows Users.

This request came from my ASP.Net project, which is hosted on intranet IIS server. The first login page is to authenticate Windows users in the company.  I need a library to do the job.  I tried some codes created long time before, but I found that the codes is not completed.  The authentication works only in Visual Studio, but not at an IIS server after deployment. I need to fix the issue.

I found that there are many ways to do that.  One is based on our existing codes with Novel.Directory.Ldap library, another on System.DirectoryServices. I tried both in one test console application.

Here some some references and constants used in the console application:

using System;
using Novell.Directory.Ldap;
using System.Collections.Generic;
using System.DirectoryServices;
using System.DirectoryServices.Protocols;
using AD_LdapConnection = System.DirectoryServices.Protocols.LdapConnection;
using ND_LdapConnection = Novell.Directory.Ldap.LdapConnection;
using System.Net;
...
private const string LDAPHOST = "xxxx.yy.zzzz.com";
private const int LDAPPORT = 389;
private const string DOMAINNAME = "yy";
private const string CN_NAME_SUFIX = "@yy.zzzz.com";

Novel.Directory.Ldap


The first one is base on Novel.Directory.Ldap:

private static bool Authenticate(string username, string pwd)
{
  bool bRet = false;
  bool connected = false;

  // connect to LDAP server
  ND_LdapConnection ldapConnLogin = new ND_LdapConnection();
  try
  {
    Console.WriteLine("Start authenticating...\nConnecting to {0}, port: {1}",
      LDAPHOST, LDAPPORT);
    ldapConnLogin.Connect(LDAPHOST, LDAPPORT);
    connected = ldapConnLogin.Connected;
    if (connected)
    {
      Console.WriteLine("Connected: {0}", connected);

      string cn = string.Format(
        "{0}{1}", username, CN_NAME_SUFFIX);
      Console.WriteLine("Binding with {0}", cn);
      ldapConnLogin.Bind(cn, pwd);
      bRet = ldapConnLogin.Bound;
      Console.WriteLine("Bound: {1}", bRet);
    }
  }
  catch (Exception ex)
  {
    string msg = string.Format(" Error message or code: {0}", ex.Message);

    Console.WriteLine(msg);
    bRet = false;
  }
  finally
  {
    if (ldapConnLogin != null && connected)
    {
      ldapConnLogin.Disconnect();
    }
    ldapConnLogin = null;
  }

  return bRet;
}

This methods depends on ldap host name, port number, and cn name(in a format like email address in our company). One thing interesting is that the exception thrown from the binding call are error codes in Message, and no implementation of ToString() method.

System.DirectoryServices


The second method is Microsoft .Net library APIs in System.DirectoryServices. The following codes are much simpler and works in the same way to authenticate a Windows user:

private static bool Authendicate2(string domain, string userName, string password)
{
  bool validation = false;
  try
  {
    Console.WriteLine("Authenticating user by AD library...");
    var ldc = new AD_LdapConnection(
        new LdapDirectoryIdentifier(LDAPHOST, false, false));
    NetworkCredential nc = new NetworkCredential(userName, password, domain);
    Console.WriteLine("Created credencial object.");
    ldc.Credential = nc;
    ldc.AuthType = AuthType.Negotiate;
    Console.WriteLine("Binding credencial...");
    ldc.Bind(nc);
    // user has authenticated at this point, as the credentials were used to login to the dc. 
    Console.WriteLine("Binding credencial is done.");
    validation = true;
  }
  catch (Exception ex)
  {
    Console.WriteLine("Exception: {0}", ex.Message);
    validation = false;
  }
  return validation;
}

References

Read More...

Thursday, December 08, 2011

In the past weeks I have been working on an ASP.Net web site application. I tried to use my ILog and LogToFile initially. However it failed miserably. ASP.Net web pages are based server and client architecture pattern. The IIS Server does not know when the web page on client side will call back. This means that I cannot keep the log file opened forever. I tried to close the log file for each message log.  I found that I could not keep the same log file since my log file name is in a patten like mylog_yyyymmdd_hhmm.log. The sever side will open another log file since the file name is kept on the server side. I could remove minutes out, but I don't like it. Therefore my original library for logging messages is not good for web site applications.

Further investigating the sever side class codes, I found that on the IIS server, writing to a text file is not allowed. I tried to write to a folder out of inetpub folder, such as C:\Log, still it is not writable.  I may be able to figure out by change IIS application pool permission, but I don't that's may cause security holes.

I had to take different strategy to log messages. I changed my log helper class to write messages to a SQL server database. This actually works fine. I realize that there are some drawbacks about this. As I mentioned in the above analysis, I cannot keep database connection open all the time. So I have to close connection for each log.  This results a very slow logging process since the database connection has to be opened and closed constantly. But it works fine.  In order to improve performance, I used delegate for log message so that if log setting is off, no db connection operation at all.  The second good practice is to use a pair methods of BeginDBLog() and EndDBLog() to allow database connection open for several log processes.

Here are some class data members in DBLog class:

# region Data members
private static DBLog _log;
private IDbService _db;
private SQLQuery _sqlQuery;
private DBLogConfig _config;
# endregion

Since the instance of DBLog is singleton, I use a method to control the instance creation. The pair methods are used for keep the instance of IDbService alive:

public static DBLog GetInstance(DBLogConfig logConfig)
{
  if (_log == null)
  {
    _log = new DBLog(logConfig);
  }
  return _log;
}

#region CTOR
private DBLog(DBLogConfig config)
{
  _config = config;
  _sqlQuery = new SQLQuery(_config.StoreProcedureName);
}
#endregion

public void BeginDBLog()
{
  if (_db == null)
  {
    if (_config != null)
    {
      _db = new DBService(_config.DBConnection,
        _config.SQLOrOracle ?
        DBService.DBType.MicrosoftSQLServer :
        DBService.DBType.OracleServer);
    }
  }
}

public void EndDBLog()
{
  if ( _db != null )
  {
    _db.Close();
    _db = null;
  }
}

Here are methods for logging messages:

public void LogMessage(string flags, LogType logType, string msg)
{
  LogMessage(flags, logType, delegate() { return msg; });
}

public void LogMessage(string flags, LogType logType,
    LogHelper.GetMessageDelegate getMessageDelegate)
{
  if (IsLogSet(flags, logType) && getMessageDelegate != null)
  {
    bool close = false;
    if (_db == null)
    {
      BeginDBLog();
      close = true;
    }
    string msg = getMessageDelegate();
    if (!string.IsNullOrEmpty(msg))
    {
      if (_sqlQuery.Parameters.Count > 0)
      {
        _sqlQuery.Parameters.Clear();
      }
      bool sqlOrOracle = _config.SQLOrOracle;
      DateTime dt = DateTime.Now;
      if (msg.Length > MAX_LENGTH)
      {
        msg = msg.Substring(0, MAX_LENGTH - 1);
      }

      _sqlQuery.Parameters.Add(SQLQuery.GetParameter(sqlOrOracle,
        _config.ParameterDate, dt));
      _sqlQuery.Parameters.Add(SQLQuery.GetParameter(sqlOrOracle,
       _config.ParameterLogType, logType.ToString()));
      _sqlQuery.Parameters.Add(SQLQuery.GetParameter(sqlOrOracle,
        _config.ParameterApplication, _config.ApplicationName));
      _sqlQuery.Parameters.Add(SQLQuery.GetParameter(sqlOrOracle,
        _config.ParameterMessages, msg));
      _sqlQuery.Parameters.Add(SQLQuery.GetParameter(sqlOrOracle,
        _config.ParameterSiteID, _config.SiteID));

      int result = _db.ExecuteSqlNoneQueryCommand(_sqlQuery, CommandType.Text);
    }
    if (close)
    {
      EndDBLog();
    }
  }
}

Notes: the above codes depend on my DotNetCommonLibrary and a class of DBLogConfig for database configuration.  The configuration class is a simple class with property getters and setters for database type, stored procedure name, and parameter names, as well as related configuration values.

Read More...

Saturday, December 03, 2011

Read Password from Console

Yesterday I was write codes to test my class for user Windows authentication. The simple console app will take user name and password as input. I would like password from console input like *** from a text box. By googling search, I found the following codes. They works as expected.

The example codes are very simple. Actually I tried to search from Console class in Visual Studio, and I found ReadKey method. I did not figure out how to get input from this method, since the keys from the methods are all in caps. Then I searched the web and found this solution. Sharing is great!

public static string ReadPassword() {
  Stack<string> passbits = new Stack<string>();
  //keep reading
  for (ConsoleKeyInfo cki = Console.ReadKey(true);
      cki.Key != ConsoleKey.Enter; cki = Console.ReadKey(true)) {
    if (cki.Key == ConsoleKey.Backspace) {
      //rollback the cursor and write a space so it looks backspaced to the user
      Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
      Console.Write(" ");
      Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
      passbits.Pop();
    }
    else {
      Console.Write("*");
      passbits.Push(cki.KeyChar.ToString());
    }
  }
  string[] pass = passbits.ToArray();
  Array.Reverse(pass);
  return string.Join(string.Empty, pass);
}

Reference

Read More...