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...

Tuesday, November 29, 2011

Siri, a New User Interface?

Apple's newly iPhone 4S has a new UI, Siri. Basically, it is a nature language based virtual assistant application. What it accepts is a question or request. Behind sense, it has linguistic analysis system to figure out the request, and provides an answer or proposed action.

Natural language conversatiotn between human and computer has been in scientific fiction or future system.  Most people or developers still accept traditional ways as a channel communicate with computer, keyboard, mouse, and touch interface as from iOS. By using language as a channel, it has been in imagination until Siri.

Apple says that the current Siri is beta version and it is true.  Based on the experiment of most people, it has limited features. However, it is a fascinate feature.  Based on a question or request, in less than 10 seconds, the input would be transferred to a web service, where the input would be analyzed and an answer or proposed action is returned. The input and out are all in voice base.  The integration with OS makes it possible to provide either voiced respond, visual result, or suggestion, or action.

I think Siri does create a new way to communicate with computer. Traditional inputs like keyboard, mouse and touch interfaces do have their limits.  For example, when you have hundreds of apps in iPhone or iPad, it would be very difficult to find or use them.  Spotlight feature on iOS does provide a convenient way to find them. Just image, if you communicated with computer OS to issue questions, suggestions and commands in natural language, it would create an abstract way to explore OS and control applications.  Apple is the pioneer in this area, but we will see similar innovations following up soon.

Right now, Siri's platform is still in a black box.  I think that by the time of next year WWDC, more detail information and API support will be available. It will be very interesting to see if it is possible to provide application level support for Siri. By that time, we should be able to see wide extension of Siri usages.

Read More...

Saturday, November 19, 2011

Xcode First Update from Apple Store

This is an update I got from Apple Store: XCODE 4.2.1. This year since I came back from Beijing vacation, I have to get chance to work on my iOS application. I intended to put the project on side since I have another important job I have to put my full energy on it. I have daily contact job which takes my day time, 8 hours. I was planing to work on iOS project if I did not have any contacts.

My current contact will be finished by the end of this year. It is mostly likely extended to another year. I hope that I will find sometime next year back to my iOS project. Even I did not have time to work on iOS codes, I did finished all the WWDC 2001 videos during summer time. I think that it is important to keep up with the technology even not working on any project.

Here is the snapshot of the update:

Read More...

Friday, November 11, 2011

Add Customization to Web.config

I have not touched ASP.NET project for about one year.  Now I am back to a new ASP.NET project. Even though it is not too hard to pick it up and add my new skills and extensions to the project, I have to constantly refer to the project I worked before.  For sure, I would not like to copy the same structure and design into the new project.  The project is a .NET 2.0 based ASP.NET, but I am planning to update it to .NET 4.0 ASP.NET MVC 3 in the next stage, most likely next month or next year, if my contract extension would pass.

One thing I like to add is customized configuration.  I prefer to define my configuration out side of web.config, because there are so many special nodes designated to ASP.NET project or web site. I know there is a way to add customized nodes there, but I want to re-use my pattern to parse XML doc with my library.

At least I have to add one node in web.config. This is very easy:

<configuration>
  <!-- application specific settings -->
  <appSettings>
    <add key="MyConfigurationFile" value="config/MyConfiguration.xml" />
  </appSettings>
  ...
</configuration>

The above entry defines an application-wide setting named MyConfigurationFile with the string value config/MyConfiguration.xml, the configuration xml file in the web site folder config. With this setting, I can get the xml file like:

string file = ConfigurationSettings.AppSettings("MyConnfigureationFile");
file = string.Format("{0}{1}",
    AppDomain.CurrentDomain.BaseDirectory, file);
...

Reference

Read More...

Working on an ASP.NET Project

Last week I started working on an ASP.NET project.  At the start, I was planning to use ASP.NET MVC 3.  I worked on MVC project 5 years ago.  That project was based on initial framework by Microsoft Patterns and Design group. Now this MVC has been changed a lots. It seems much easier to work with.

The first thing was a spike on this new framework. I tried one example from ASP.NET MVC web page.  One thing I don't like is that the project is integrated with Microsoft Entity Framework and SQL Express.  I had to break the connection to the SQL db to make it work. It took me one day to get main web page working.

Then I deployed to  our dev IIS, which is in a box of Windows Server 2008 R2 with .NET 2.0, 3.5 available. Unfortunately, the initial deployment was not working.  The project I created was based on MVC 4 and .NET framework 4.0.

I installed .NET framework 4.0. Still the web page on IIS was not working. I installed ASP.NET MVC package on the box. Still not working.  It looks like the Razor engine was not configured on IIS. I got 404 error, denying access to the content of a path, which is the basic structure of {site}/{controller}/{action}/, with no .aspx. Finally, I got it working by installing WebMatrix.

With all those installation, my MVC example web page was displayed on the IIS. I was very happy to tell my project BA, who is the main force to push this project with new framework. Unfortunately, on the second day, I realized that all the existing web pages stopped working. That's really bad news.

Since my project is in a very tight schedule, I made decision to roll my project back to a .NET 2.0 based ASP.NET web project. This is the one consistent with our existing web pages. I blamed Microsoft for IIS not being able to support .NET 2.0 and plus web pages.

Two days later, I spent several hours on IIS configuration. I saw that all the web sites on the deb box was based on application pool by defaults, which is .NET 4.0.  In the screen of application pool, there are previous ones based on .NET. After I changed the AP for existing web sites to .NET 2.0, all those sites are back to work. It is the updates that causes the AP changed. Still I think the installation should not change those AP settings.

That's quite up and down experience. I have learned good lesson about IIS configurations. IIS does support parallel .NET frameworks by specifying AP. Just imaging IIS as an application, and all the web sites are web pages based on all libraries.  The IIS is a complicated application. With IIS management console, the configuration can be set for web sites, which supports previous ASP.NET projects.

I'll continue to work on this project based on .NET framework 2.0 and ASP.NET. The next phase is to update it to .NET 4.0, hopefully with MVC 3.

References

Read More...

Thursday, October 27, 2011

Procedures in Oracle Server and SQL Server

Recently I have been working on a project to provide data for a third party application, called ParcView. The PV is used to view data source from OPC and databases. The requirement of one data source is from Oracle database.

PV provides a system configuration of SQL templates for data source in data, current, tag list and tag information, four major areas (some others are rarely used).  I have done a lots for SQL database server, and some of Oracle database. Based on the recommendation, if the template SQL scripts are too complicated, it is recommended to use stored procedures as a way to provide data.

In SQL SP, data source can be directly returned by using SELECT statement.  However, in Oracle, this type of return is not available.  What I found is that all the data row set has to be returned by a OUT parameter SYS_REFCURSOR type. This makes it is impossible for me to implement in the same way as I did for SQL server before.

I have tried another way, view with parameters. Basically, a package is defined with functions and procedures. They are in a structure of property: get in function and set in procedure.  A local variable in the package as a storage for property values.  Then the view references to the functions are parameter.  Before calling the view, a PL/SQL command exec is called first.  This strategy is back to he none-SQL query problem.  PV does not have a way to call it. As a result, this strategy hits the dead wall again.

It is really hard for me to put scripts on database server side. The lesson I learned is that the PV should problem a kind of interface based APIs to allow plugin components.  Now I recall that the provider of PV does have a way to add customized data source, but we have to ask the company to write codes to do it. They will charge for the service.

Maybe I should ask the computer to provide a component to allow customized plugin to provide data source.


Read More...

Saturday, October 15, 2011

Extension Class: LogHelperExt

I wrote a helper class for logging text messages long time ago. Recently I tried to write a document and demo project about using this helper class.  During the writing process, I found that the helper class can be further enhanced.

The helper class provides some static methods for writing a message string. One of  basic method takes several parameters, with ILog instance as its first parameter.  I realized that actually this instance is not needed to be passed in since this is a singleton instance. Why should I pass it every time? I started to simple this method.  The strategy I took is to add another helper class, called as LogHelperExt. I tried to avoid to change LogHelper because this class has been used in many places.

The new helper class contains much simple APIs. The first one is Initialize:

public class LogHelperExt {
  private int m_Spaces;
  private int m_indents;

  public static ILog Logger { get; private set; }
  public static LogHelperExt Instance { get; private set; }

  private LogHelperExt() : this(0)
  {
  }

  private LogHelperExt(int indents)
  {
    m_Spaces = 0;
    m_indents = indents;
  }

  public static LogHelperExt Initialize()
  {
    return Initialize(null, 0);
  }

  public static LogHelperExt Initialize(ILog log)
  {
    return Initialize(log, 0);
  }

  public static Initialize(ILog log, int indents)
  {
    if ( Instance == null )
    {
      Instance = new LogHelperExt(indents);
      Logger = log;
    }
  }
  ...
}

The Initialize method is to pass ILog instance in. This method is normally used once. An additional indent value is passed for a new feature of indenting spaces for logged messages.

The commonly used API for writing messages is as followings:

public LogHelperExt WriteMessage(string flags, LogType logType, GetMessageDelegate getMessage)
{
  if (getMessage != null )
  {
    LogHelper.WriteMessage(Logger, flags, logType,
        delegate()
        {
          return string.format("{0}{1}",
            m_Spaces > 0 new string(' ', m_Spaces) : "",
            getMessage):
        }
  }
  return this;
}

This interface is much cleaner than before. Notice that the API method is an instance method with data type of the class itself. I intended to design this class in this way, fluent interface pattern, so that I can chain the calls just in one line.

The indention and un-indention feature are added to this class:

public LogHelperExt Indent() {
  m_Spaces += m_indents;
  return this;
}

public LogHelperExt Unindent {
  m_Spaces -= m_indents;
  if ( m_Spaces < 0 )
  {
    m_Spaces = 0;
  }
  return this;
}

With above changes, I will use LogHelperExt for logging messages. Here is the example I wrote in my demo project:

class DemoClass {
  public void TestMethod()
  {
    LogHelperExt.Instance.WriteMessage("d", LogType.Debug, "Enter TestMethod").Indent();
    ...
    LogHelperExt.WriteMessage("d", LogType.Debug, "Test message");
    ...
    LogHelperExt.Instance.UnIndent().WriteMessage("d", LogType.Debug, "Leaving TestMethod");
  }
}

Read More...

Wednesday, October 05, 2011

We'll Never Hear Steve Jobs Live Voice

Today is a sad day. Steve Jobs passes away, at his age 56.  I wrote a blog in my Chinese blog to remember him.

It is too sad to hear the news. Personally, I feel that Apple and Steve Jobs do change my life. Not just only a computer or device like iMac or iPad or iPhone, Steve Jobs' life and his legacy have trenmendous impact on me for everything, in addition to my pursuing my software development knowledge and skills in Mac OS and iOS.

I am so fortunate to start my journey to use Apple product while Steve Jobs was alive (in year 2007).  It has been an amazing experience. I just begin my new journey, and it will continue on.

Read More...

Saturday, October 01, 2011

Json.Net Issue: does not support namespace in XML

Yesterday I had a talk to a developer at work. She came from the same city as my hometown where I was grown up. She was working on a project to import thousands of XML files SQL database. I recommended my dotNetCommonLibrary.dll, where I have a wrapper class for Json.Net.  The wrapper class provides several APIs to convert XML string to an instance of a class and vice versa.  I have used this feature to convert many application XML configuration settings to instances.

However, when I saw her XML files, I noticed that those XML files contains namespaces, which are used in XML nodes as prefix. I had never tried those types of XML documents before. Today I tried a simple XML file with a namespace for testing. Unfortunately, it looks like that Json.Net converter does not support XML with namespaces.

Example of XML with namespaces:

<?xml version="1.0" encoding="UTF-8" ?>
<Root>
  <b:Log xmlns='http://www.w3.org/1999/xhtml' xmlns:b='http://www.google.com/2005/gml/b' >
     ...
  </b:Log>
</Root>

I think this type XML files are very common. I have to find out a way to remove namespaces and use only local names in XML notes for instance mapping by Json.Net

It was a good talk. At least I find my wrapper class has to provide an API to remove namespaces from an XML string.

References


Read More...

Sunday, September 25, 2011

My Collection of Programming Podcasts

Podcasts are important information resources I have in the past years. I listen and watch for those audio and video podcasts during slices of my time, on the way to and from work, lunch time, weekends, and anytime available for me such rest time during camping.

Basically, I sync my Apple mobile devices at lest once a week through iTunes. Here are the collection of podcasts I have right now:

Audio/Video podcasts:


  • CNET: Buzz Out Loud (Tech news)
  • DailyAppShow (iOS device app reviews, videos)
  • GeekBeatTV (Tech video show)
  • Hanselminutes (.Net tech news/programming)
  • HerdingCode (.Net programming)
  • iPone/iPad/Android App Reviews by CrazyMikesapps (videos)
  • jQuery for Designers - screencasts and turotirals (videos)
  • CNET: Loaded (videos)
  • Mac Geek Gab
  • the Maccast for Mac Geeks by Mac Geeks
  • MacMost Now - Mac and iPhone Tips and Tutorials (videos)
  • MacTalk
  • Macworld podcasts
  • .Net Roks!
  • ScreenCastsOnline Free Version (videos)
  • Tech NightOwl
  • Today in iOS Podcast - The Unofficial iOS, iPhone, iPad and iPod Touch News and iPhone Apps Podcast
  • Typical Mac User Podcast
  • WebBeastTV(HD) (videos)
  • Wired's Garget Lab Video Podcast (videos)
iTunesU:

  • UCDavids University of California: Introduction to iPhone Application Development (fall 2009)
  • Stanford Univierty: Developing Apps for iOS (spring, fall 2010, summer 2009)
  • RWTHAACHEN University: iPhone Application Programming WS 09/10
  • Apple: iPhone Getting Started Videos (08)
  • University of Utah: iPhone Programming Association - Audio
  • Apple Developer Connection: iPhone Tech Talk World Tour (09)
  • Apple: iPhone Tech Talks (07)
  • WWDC 08, 09, 10, 11
Above list is only the one for my programming and tech news information and updates. In addition to that, I also have a wide range of other topics and areas I listen and watch on daily basis, as you can see in my screen snap-shots.

Read More...

Sunday, September 18, 2011

My iOS Development Status

I have not been back to my iOS development since my Beijing vacation back. May be I am just too lazy or too busy with something else as excuse. One of reasons is that I want to do it in Xcode 4.0 and iOS 5. I got my Xcode updated last month. iOS will be released anytime soon either this month or in October.

For sure when iOS is out, I'll be back to my iOS app development schedule. At lease I'll allocation some time a week. First thing I have to update my codes to iOS 5.0. Then I'll finish my app and continue my next project.

The good thing that I have been in touch with iOS and OS technology is that I finished WWDC 2011 videos. Now I find out some more back to WWDC2008 and other videos from iTunes U. I have kept my after work time, some of them, view those training materials. In this way, not only I am refreshed by the new materials, but also I learnt a lot about some of new concept I don't know before.

In addition to above activities, I have been kept writing my notes on WWDC2011 in my Chinese blogs, just a way to review and to share my iOS exploration and experience.

Read More...

Saturday, September 10, 2011

Add Zoom Image Feature to Blogger

Recently Google's BLogger has been redesigned with much more new features. The original openness features are still available. Still I don't like the way in Blogger to resize images in narrow width so that it is hard to see. I understand that exploded image would distract the whole blog layout. Therefore, I have been thinking about adding a feature to zoom images in Blogger.

Last weekend I spent about whole day to find a suitable solution and enhanced it with my updates.  The strategy is based on jQuery and CSS. I found it in a blog in CSS Globe. It is really easy to use. Add a CSS and two script links to Blogger HTML settings first. After that it is ready for use.

For example, to add zoom feature to an image in blog, add class called as "zoom" to the image's parent anchor HTML tag:

<a class="zoom" href="test.png">
  <img src="test2.png" border="0" width="300">
</a>

It works great; however, there is one thing I found not perfect. In case of an image with narrow height, there is a big gap on the top in its zoomed image. I would like to let the zoom image auto-adjust its height: either to the image height to at most the height defined in the CSS.

Here are the steps to add my enhanced zoom feature to Blogger.

Update Blogger HTML Settings

The first thing to do is to update your Blogger HTML settings. It is recommended to backup your HTML settings before any changes.

Step 1. In your Blogger Dashboard, click Template and then Edit HTML

Step 2. Find your blog CSS sections. Those CSS definitions should be ended by

]]></b:skin>

Step 3. Copy and post the following CSS codes into your CSS sections before ]]></b:skin>

/*  following css for zoom effect is copied from
http://www.spiceupyourblog.com/2011/05/amazing-jquery-image-zoom-effect-for.html
*/

#easy_zoom{
  /* default width and height, those settings can be optionally set in
     anchor element attribute: zoomboxwidth and zoomboxheight */
  width:500px;
  height:400px;
  border:5px solid #eee;
  background:#fff;
  color:#333;
  position:fixed;
  top:35px;
  left:50%;
  overflow:hidden;
  -moz-box-shadow:0 0 10px #555;
  -webkit-box-shadow:0 0 10px #555;
  box-shadow:0 0 10px #555;
  /* vertical and horizontal alignment used for preloader text */
  line-height:400px;
  text-align:center;
}

The top and left values are the position of zoom box.  You adjust above top and left values for your blogger template.  The width and height values are default zoom box size.   You may change them according to your needs.

Step 4. Find the following piece of codes in your HTML template:

<head>

This is the end of head tag in your HTML template.

Step 5. Before the head tag, copy the following codes:

<!-- the following scripts for zoom effect are copied from 
http://www.spiceupyourblog.com/2011/05/amazing-jquery-image-zoom-effect-for.html
add class="zoom" in image a tag and it will have zoom effect!
 -->

<script src='https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js' type='text/javascript'/>
<script src='http://davidchu-javascript-libraries.googlecode.com/files/easyZoom1.1.js' type='text/javascript'/>
<script type='text/javascript'> 
$().ready(function() { 
  $(&#39;a.zoom&#39;).each(function(i) { 
    $(this).easyZoom();
  }); 
}); 
</script>

The above codes add links to jQuery library and my updated EasyZoom library to you blogger. The libraries contains a function easyZoom for any HTML anchor tag with class "zoom" to add mouse hover event, i.e., zoom effect to your images!

Step 6. Save your new HTML template.

You do this (6 steps) only once. Now it is ready for you add zoom feature to your blogs.

Edit Image in a Your Blog

Now you can add zoom effect to your images in your blog posts.  Normally, after your adding images to your posts, Blogger will add some HTML tags for your image.  You should simplify those tags like this:

<a class="zoom" href="test.png">
  <img src="test2.png" width="300" ...>
</a>

The key to enable zoom feature is to add "zoom" class in anchor or a HTML tag. Here ... are any other settings you may want to your image, for example, align to left, center or right, or border. The width attribute value is based on your blog layout, and you may change it for best result.

You only need to update your Blogger HTML once in above 6 steps.  To add zoom feature to your image, all you have to do is to enable HTML edit and to add "zoom" to your anchor tag for the image. Basic knowledge about HTML will be great help, but it is not required.  My recommendation is to learn some basic HTML and you will be able to enhance your blog with great self-satisfaction.

Examples


Here are some examples of images with zoomable feature. The first one is the log of jQuery without customized height. As you can see there is big gap in the zoom box:



and again with customized height to remove the gap:



John Resig is an application developer at Khan Aademy. He was a JavaScript tool developer for Modizlla Corporation. He is also the creator and lead developer of the jQuery JavaScript library.



jQuery is a crosse-brower JavaScript library designed to simplify the client-side scripting of HTML. It was released in January 2006 at BarCamp NYC by John Resig. Used by over 46% of the 10,000 most visited websites, jQuery is the most popular JavaScript library in use today.


Advanced Topics


This technique is based on jQuery library. jQuery is a great JavaScript library with a rich APIs to enhance HTML documents. One of great features is that jQuery let developers concentrate on codes without worrying various browsers. It just works.  Another feature is that jQuery is so tiny small. Developers can easily add features based this platform, just like this EasyZoom library.

In addition to jQuery library, you need to add this EasyZoom JavaScript library. I put my updated codes on Google Code Project.  It is an Open Source library. You can take it or modify for your needs. I'll keep my codes there forever, but if you concern its availability, you may move it to your site, your Google Code Project or any other places.

The logic of this zoom feature is based on JavaScript and CSS. JavaScript codes above will be loaded when your blog is opened first time. The codes will find all anchor HTML elements with class "zoom" and pass those elements to JavaScripts. The magic happens in the function call, where mouse hover event, a dynamic zoom box with image referenced in the anchor, and CSS style are created.

Another note about this is that this technique is based on two images in your blog. Blogger normally add them when you update an image. The image element is a smaller size image and it is displayed in your blog. Since the image is smaller, your blog loading process is faster. Anther image Blogger added is an image its parent anchor element, with large size image. It is only be loaded when the image is clicked. This image is used in the zoom box.

I may add additional features to this easy-zoom library. For example, add a caption for the zoomed image. The caption can be easily defined in your blog.

References

Read More...

Saturday, September 03, 2011

SQLPlus Debug and VIM Find/Replace

Yesterday I was asked to help to resolve some issues for a piece of PL/SQL codes, which was provided by our client support. I was working on only error issues, nothing related to its logic. I spent about 2 hours and finally almost got the script running OK (it was too late in the afternoon). Here are two notes about the work.

First, I needed to debug PL/SQL procedure codes. We were using SQL*Plus command console. For SQLPlus command codes; I saw that command prompt is used to print out messages, but I this command does not work in a block of procedure codes. Quickly I found the command which can be used for PL/SQL procedure debug. It is actually a very simple one, and I used this one long time ago. Here is my note on this again:

SET SERVEROUTPUT ON
dbms_sql.output.PUT_LINE('message');
...
SET SERVEROUTPUT OFF

The second note is about using VIM to add the about debug command dbms_sql.output.PUT_LINE in to codes. The reason I wanted to use VIM was that a block of similar codes are in a repeatedly pattern (the following codes are mock and simplified ones):

strDDL := 'create synonum ' || '&username' || '.AUsers for ' || '&newUser' || '.AUsers';
nCID := dbms_sql.open_cursor;
dbms_sql.parse(nCID, strDDL, dbms_sql.v7);
nCount := dbms_sql.execute(nCID);
dbms_sql.close_cursor(nCID);


strDDL := 'create synonum ' || '&username' || '.BUsers for ' || '&newUser' || '.BUsers';
nCID := dbms_sql.open_cursor;
dbms_sql.parse(nCID, strDDL, dbms_sql.v7);
nCount := dbms_sql.execute(nCID);
dbms_sql.close_cursor(nCID);

...

I did not want to manually type in the debug commands after the first one in each block. That's too tedious. I decided to use my gVIM (for Windows), using its power to get my codes just in one Find/Replace command. This can be done by grouping feature in Find/Replace command, since I wanted to use partial codes in the first line. I figured out the following VIM command:

:%s\(strDDL :=\)\(.*\);\n\(.*\n.*\n.*\n.*\)/\1\2;\rdbms_output.PUT_LINE(\2);\r\3/g

Notes on above command:


  • Replace command: %s/find/replace/g where g is for all.
  • In find section, use \(...\) to mark a group. In my above command, there are 3 groups and the 2nd ad 3rd groups will be reused in replacement section.
  • The group name used in replace section is reference by \#, such as \2 and \3.
  • The line break in find section is \n
  • The line break in replace section is \r


This is the result:

Read More...

Sunday, August 28, 2011

Open/Closed Principle: Delegate Example

In object-oriented programming, the open/closed principle is a very important principle. Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification. Recently I tried to summary some commonly used components in a serials of documents. I found that I have used delegate in my LogHelper class. This reminds me about my OCP.

I was not intended to use delegate as a way to extend my log feature. I was using it to avoid building a message string but not actually used for logging. I thought it will be nice to use a pointer to function which returns a string. So that the function would be called dynamically only if logging is enabled.

public delegate string GetMessage();

public static class LogHelper {

public void WriteMessage(
ILog log, string flag, GetMessage getMessage)
{
if (log != null && getMessage != null
&& log.IsLogSet(flag))
{
var msg = getMessage();
log.write(msg);
}
...
}


Here is an example of the usage:

LogHelper.WriteMessage(log, "d", delegate() {
return string.format("MyObject: {0}",
myObject.ToString());
};



As shown in above example, user can build a simple or complicated string for logging. Since the building codes are in a dynamic delegate. The delegate will only be called when the log flag "d" is enabled.

I think that my design of LogHelp class is a typical way to OCP. Here is another example to use the same method to enable indention and un-indention for messages:

class DataProcess {
private int m_indention = 0;

private void LogMsg(bool indent, GetMessage getMsg)
{
if ( getMsg == null )
{
return;
}

if (indent)
{
m_indention+= 2;
}
else if ( m_indention > 0 )
{
m_indention -= 2;
}
else
{
m_indention = 0;
}

LogHelper.WriteMessage(log, "d", delegate() {
return string.format("{0}MyObject: {1}",
new String(' ', m_indention),
getMsg());
};
}
...
}




Read More...

Sunday, August 21, 2011

Create Materialized View

This blog is about how to create a materialized view in SQL server database. By creating a materialized view, you can dramatically improve query performance. I learned this by my experience. Here are some key notes about the process.

Create a View



The first step you have to create a view. The first requirement for materialized view in SQL server is that a special WITH SCHEMABINDING has to be used for the view.
CREATE VIEW [dbo].[vMyView] WITH SCHEMABINDING
AS
SELECT rawid,
readingdate,
CAST(VALUE AS FLOAT) AS VALUE,
name
FROM dbo.myRawDataTable
WHERE ( VALUE IS NOT NULL )
AND ( Isnumeric(VALUE) = 1 )
AND Name LIKE '%my_pattern%'


The second requirement is to make sure there are any keys in the view. For example, you can include key column or combination of columns as a unique identifier. This key will be used to create INDEX for the view.

Add a Index



The materialized view actually holds a block of data with Index. This makes view fast for retrieving data. For example, for above view, a INDEX is created:

-- Create UNIQUE CLUSTERED index on the view
CREATE UNIQUE CLUSTERED INDEX IVW_vMyViewUniqueIndex
ON [vMyView] (rowid, name, readingdate)


The Index is created depending on your query. With this Index, you will see great performance improvement, specially again huge amount of data.

Use (NOEXPAND) in SQL Query



With above preparation, the view is ready for use. However, I noticed that a special option has to be used in SQL query in order to take advantage of the Indexed view, for example:

SELECT *
FROM [vMyView] (NOEXPAND);


This NOEXPAND has to be used in SQL Standard Server. In SQL Enterprise Edition Server, this is not required (but you have to pay big bucks).

Conclusion



Materialized View can improve SQL query performance dramatically, just like adding property Index to tables. The disadvantage is that the MV will take some disk spaces. You have to balance the weight in your real cases.

Read More...

Sunday, August 14, 2011

Finished Watching WWDC 2011 Videos

Today I finished watching all the WWDC 2011 videos. I spent most of after-work hours to watch those shows. It is good to get an overall view of all the technologies used in iOS 5, even some I may not use at all and some are hard to digest.

I also started to write my notes in Chinese about WWDC 2011 shows. However, the notes are far more behind my watching schedule. I could not keep up my notes with my watching progress, and eventually I decided to left go behind. Right now my notes are close to the end of 100 serials. They are still 200, 400 and 500 serials to be written. I think it is good review when I write notes, and I'll keep it up to the end.

Read More...

Monday, August 01, 2011

Updated to Xcode 4.1

Today I updated me Xcode to 4.1. It is a free version available from Apple store. That means you either have to have Snow Leopard or Lion if you want to get it. Before Lion's release it was $5.00 from Apple Store. I have not started my iOS development for a while since I have been kept watching WWDC 2011 videos. Right now I am in the half way through 400 sessions and only 500 serials in my schedule. It is really good to learn OS and iOS new features from those session videos.


The update of Xcode is 3GB+, almost as big as Lion. After the installation the Install Xcode app stays in Applications folder. I removed it from there after the installation (I made a copy of this package to my external HD). The following is the welcome window.


I'll have to squeeze time to go back to my development.

Read More...

Sunday, July 24, 2011

Code Formatter

Last week I was working on some T-SQL query codes. I remembered that I used PL/SQL developer tool to reformat my SQL codes by using Beautifier. I could not find similar tool in SQL Server Management Studio, at least for SSMS 2005/2008. I googled web to see if there is any tools available.

To my surprise, I found couple very nice web on-line tools called as code formatter. For example, Instant sQL Formatter is the tool I want. In addition to parse codes into a nice format, it also does basic syntax checking. The only thing is missing is the spaces for indention.

In addition to TSQL, I found several other web tools for code formatter:

Read More...

Sunday, July 17, 2011

Finished Watching WWDC 2011 Videos in -Halfway

In the past weeks, I have been in a fast-paced way to watch WWDC 2011 videos. Right now I have finished 100(App Frameworks), and 300(Developer Tools) serials. Still three sections left: 200(Core OS, 13), 400(Graphics, Media and Games, 24), and 500(Internet and Web, 19).

I have also made some nodes in my Chinese blogs about WWDC 2011.

WWDC exposed more detail changes in iOS and Mac OS with new framework and APIs. For example, full screen feature is a very nice thought designed bases on iOS. Windows have full screen since its start, Windows 3.0. However, Mac OS full screen has more support from its core internal. App's will receive many events such as willXXX and didXXX for full screen status. With those events, app developer can prepare UI for better user experience and usage. In terms of OS, the full screen has consistency UI for full screen such as enter, exist and keyboard shortcuts. Full screen apps flow fluently in Mac OS.

Another group of great features are auto-save and versions. Those features are backed by app with Cocoa new APIs. Basically, this is a repository for software source codes, but it has been expanded to Mac OS app. It will be up to app developer to implement the feature. Save and versions are integrate part of Mac OS. As one of Apple software engineering in one session about this topic said, what is if further of Mac OS Cocoa? It may be the long time Quit will be gone. Users will not need to take care apps in Mac OS. Since everything will be auto-saved, why should apps with those features stay in OS when they are not in use? This will greatly enhance the experience of using Mac with great resources releases by inactive apps.

Read More...

Sunday, July 10, 2011

Using DIV to layout side-by-side blocks

I often need to layout my contents in two blocks side-by-side, with left side block as a warning message as example. This can be done easily by using CSS and HTML. Here are the tips.

Example layout



First, let's look at the example layout. To visualize the side-by-side blocks, I added a border container, which can be removed.

First DIV block on the Left


When using percentages, you usually have to play around a bit to get things to look the same in IE, Safari, Chrome and Firefox.

Right block


This is a tutorial on how to use CSS to create a simple two column layout.

The styles for the blocks are defined in CSS classes in the <head> section of HTML.

This the end of 2 column side by side layout.


Define CSS classes



Define the following style classes in HTML head section:

<head>
...
<style type="text/css">
....
.boxLeft {
float:left;
width:20%;
border:1px solid;
padding: 1%;
margin:1% 0 1% 1%;}

.boxRight {
float:right;
margin: 1% 1% 1% 1%;
width:75%;}

.clear {
margin: 0;
padding: 0;
clear: both; }
...
</style>
...
</head>


Use CSS classes to layout 2-blocks side-by-side



With above CSS classe definitions, they can be used in the body section to layout 2 blocks of text side-by-side:

<body >
...
<!-- containner -->
<div style="border:2px solid;">
<!-- Left block -->
<div class="boxLeft" style="background:green">
<h2>First DIV block on the Left</h2>
<p>When using percentages, you usually have to play around a bit to get things to look the same in IE, Safari, Chrome and Firefox.</P>
</div>
<!-- end of left block-->
<!-- right block -->
<div class="boxRight" style="background:#dff">
<h2 >Right block</h2>
<p>This is a tutorial on how to use CSS to create a simple two column layout.</P>
<p>The styles for the blocks are defined in CSS classes in head section of HTML.</p>
</div><!-- end of box block -->
<div class="clear"></div>
</div><!-- container -->
<div>
<p>This the end of 2 column side by side layout.</p>
...

References

Read More...

Friday, July 01, 2011

No Overflow for a Simple Math Calculation

I watched WebBeat podcast one day in the last month. One video show got my attention: Explaining visual math in a simple way. I wrote a blog on my Chinese blog. It is very interesting to resolve a math multiply by visualization graphs. However, this method only applies to multiply of 2 digit numbers, and it becomes tedious when there carrier forward in the last and middle numbers.

This reminds me a long time puzzle problem: how to resolve overflow issue when the result of multiply of two integers is too big. I recall the traditional method of multiply algorithm and relate it to this visualization. Soon I realize that I could resolve the overflow issue by creating a small app. I gave it a try with Javascript and I got it worked out! I am very happy with the result. No more overflow no matter how big numbers they are!

Here is my Javascript function:

function v1timesv2(v1, v2) {
  var x = ''; // result
  var i = 0;
  var j = 0;
  var r;
  var r1;
  var r2;
  var k;
  var tempVal;
  var preTempVal = '';
  debug ('v1: ' + v1);
  debug ('v2: ' + v2);
  for (i= v2.length-1; i >= 0; i--) // v2
  {
    r2 = 0;
    tempVal = '';
    k = preTempVal.length;
    for (j=v1.length-1;j >=0; j--)  // v1
    {
      if ((k--) > 0)
      {
        r2 += Number(preTempVal[k]);
      }
      r = v1[j] * v2[i] + r2;
      r1 = r % 10;
      r2 = 0;
      if ( r > 9 )
      {
        r2 = (r - r1) / 10;
      }
      tempVal = r1 + tempVal;
    }
    if ( r > 9 )
    {
       tempVal = r2 + tempVal;
    }
    debug('intermediate calculated result: ' + tempVal);
    // Get the last char as result
    x = tempVal[tempVal.length - 1] + x;
    debug('intermediate result: ' + x);
    // Get the remaining as previous val
    if ( tempVal.length > 1 )
    {
      preTempVal = tempVal.substr(0, tempVal.length - 1);
    }
    else
    {
      preTempVal= '';
    }
    debug('== carry forward result: ' + preTempVal + ' ==' );
  }
  x = preTempVal + x;
  debug('>>final result:    ' + x);
  debug('>>verified result: ' + Number(v1) * Number(v2) + ' (' + v1 + ' x ' + v2 + ')');
  return x ;
}


This may not be the best codes. Please let me know if you can simplify my codes. Download my numberCalc.html and drop it to a browser. I challenge if you can break my codes with an overflow!


References


Read More...