Life & Technology

Handful lessons in different areas of technology and life in general.

Monthly Archives: April 2008

Extension Method: Truncate string

If you’re like me who don’t like to display all the contents of my item’s description (not efficient if length is more than 5000 words) in a full blast on every record that I have on my database, by having the function sitting as an extension method, I can easily call this method to truncate or limit the display of that description to a specified given length and the truncated string will then be replaced by a “…”

Here’s the code of how I create it:

   1: public static class StringEx
   2: {
   3:     /// <summary>
   4:     /// Truncates the string to a specified length and replace the truncated to a ...
   5:     /// </summary>
   6:     /// <param name="text">string that will be truncated</param>
   7:     /// <param name="maxLength">total length of characters to maintain before the truncate happens</param>
   8:     /// <returns>truncated string</returns>
   9:     public static string Truncate(this string text, int maxLength)
  10:     {
  11:         // replaces the truncated string to a ...
  12:         const string suffix = "...";
  13:         string truncatedString = text;
  14:  
  15:         if (maxLength <= 0) return truncatedString;
  16:         int strLength = maxLength - suffix.Length;
  17:  
  18:         if (strLength <= 0) return truncatedString;
  19:  
  20:         if (text == null || text.Length <= maxLength) return truncatedString;
  21:  
  22:         truncatedString = text.Substring(0, strLength);
  23:         truncatedString = truncatedString.TrimEnd();
  24:         truncatedString += suffix;
  25:         return truncatedString;
  26:     }
  27: }

and applying the code above like this:

   1: string newText = "this is the palce i want to be, Cindys is the place to be!";
   2: Console.WriteLine("New Text: {0}", newText.Truncate(40));

I already posted this on Extension Method site.

Extension Method: Get total Word Count of a string

Using regular expression and Extension Method in C#, code below provides a simple way to count all words to a given string excluding all whitespaces, tabs and line breaks.

   1: using System.Text.RegularExpressions;
   2:  
   3: public class MyExtension
   4: {
   5:     /// <summary>
   6:     /// Count all word occurrence
   7:     /// </summary>
   8:     /// <param name="input">string to begin with</param>
   9:     /// <returns>int</returns>
  10:     public static int WordCount(this string input)
  11:     {
  12:         var count = 0;
  13:         try
  14:         {
  15:             // Exclude whitespaces, Tabs and line breaks
  16:             var re = new Regex(@"[^\s]+");
  17:             var matches = re.Matches(input);
  18:             count = matches.Count;
  19:         }
  20:         catch
  21:         {
  22:         }
  23:         return count;
  24:     }
  25: }

and we could use this code like this:

   1: string word = "the quick brown\r\nfox    jumps over the lazy \tdog.";
   2: Console.WriteLine("Total Words: {0}", word.WordCount());
   3: // Output: Total Words: 9

The code is also posted in Extension Method website.

Know more about Regular Expressions.

Technorati Tags:

Ocean adventures starts at Manila Ocean Park

ocean_park
Last week, I invited my cousins to stay in our apartment for the reason that we have a surprise for them — a trip to Manila Ocean Park!

Early morning, I woke them up and said to get dress and we’ll go some place they never been to (including me!). They immediately rushed to the comfort room to take a bath and make themselves comfortable with their dress.

And of course, my little greta is so excited too even though she doesn’t know what is happening around her. The important thing for her is the word “aalis sya…?” which denotes “sya” as “her”. So cute!

We rode 2 taxis. One taxi to my wife, Christina together with Margrette, Jessa, Mae and Mai-Mai. Nikki, Michelle and Binok are with me on the other taxi. It is an exciting experience coz we all don’t know the place and what it is look like in real (we only saw the place when Jessica Soho feature this on her show last Saturday). I decided to take them to this place because of unique feature that this place will offer and also of the experience that they will get from here.

We arrived at around 11:00 AM and waited more than 30 minutes because we’re not complete yet, my wife and my cousins are not here yet.

They arrived almost 12:00 PM already and the first thing we did was to shoot pictures!

The fare:

Adult: Php 400.00

Children: Php 350.00

I think the entrance fee is fair enough considering the maintenance of the place, feeding of all fish and employees.

The place is very very very educating especially to students who like to learn more and see the fish live not just by seeing only on their textbooks. Very informative, every aquarium includes a “manifesto” of fish origin and scientific name.

One window that really catches my attention and I personally like is the eel that I forgot the name! Anyway, here is the photo:

Manila Ocean Park Eel image 

These little creatures are so cute and enjoyable to watch!

My comments:

One thing I noticed during our stay on the park are the yellow-shirted employees which they call them Park Guide assistants. They are the one explaining to people what the name of the fish, how they live, how they eat, etc etc. But they only cater foreigners(?). They only assist foreigners along their way explaining all those fishes to them. What about us?

Another thing is that only few employees are visible during and after the tour. Maybe because its a weekday? I dont know.

Dugong and Butanding are endangered species that we didn’t see in real. Only pictures are being posted.

The spotlight that displays screen saver shows Windows XP taskbar! Are you kidding me? Does you version of XP do not have a hide feature? Geez!

Overall impression:  The place is a good way to educate people to the wonders of the sea and at the same time preserve our sea creatures that are tagged as endangered. I hope people behind this wonderful park can maintain the place the way it is now.

Another one for the Philippines! Hooray!

See more of my pictures at my Picasa Web Album.

GISMapWindow 4.5: Enhancing Document Launcher Plugin

I was introduced to this Open Source software some time in February of last year when some group of people made a demo on using their software together with this as a bundled product. I was personally amazed not by their custom made product but by the way GISMapWindow application operates. It eases the way and process of working with maps, yes maps, GISMapWindow is according to their website:

MapWindow GIS is an open source GIS mapping application and set of programmable mapping components. Because it is distributed as an open source application under the Mozilla Public License distribution license, MapWindow GIS can be reprogrammed to perform different or more specialized tasks.

And now, after that demo, I’ve been spending the last two weeks fiddling around and getting used to this wonderful application as this is required as part of my recent project which involves integrating maps to our solution. Spending hours reading post on the forum and learning more from them. One post from a member that catch my attention is an enhancement request on the functionality of the existing Document Launcher plugin. He specifically asks if this plugin will support to have an additional toggle button that allows him to choose whether or not to execute the attached document on the specified shape when clicked. The FileOrUrl field execute action will then be bypassed.

So I started to download the source codes for GISMapWindow and adjusting the plugin to grant this request.

Below are the codes added and adjusted to the DocLauncher plugin:

   1: Private Const _btnName As String = "LaunchDocument"
   2: Private Const _toolTip As String = "Enable/Disable Open external document"
   3: Private _bOpenDoc As Boolean
   4:  
   5: <CLSCompliant(False)> _
   6: Public Sub Initialize(ByVal MapWin As MapWindow.Interfaces.IMapWin, ByVal ParentHandle As Integer) Implements MapWindow.Interfaces.IPlugin.Initialize
   7:     'This event is fired when the user loads your plug-in either through the plug-in dialog 
   8:     'box, or by checkmarking it in the plug-ins menu.  This is where you would add buttons to the
   9:     'tool bar or menu items to the menu.  
  10:     '
  11:     'It is also standard to set a global reference to the IMapWin that is passed through here so that
  12:     'you can access it elsewhere in your project to act on MapWindow.
  13:     g_MapWin = MapWin
  14:  
  15:     ' Create a new toolbar and a new button with an icon attached on it
  16:     ' Added 04/01/2008 by Earljon Hidalgo
  17:     Try
  18:         Dim tbr As MapWindow.Interfaces.Toolbar = MapWin.Toolbar
  19:         tbr.AddToolbar(_toolbarName)
  20:  
  21:         Dim btn As MapWindow.Interfaces.ToolbarButton = tbr.AddButton(_btnName, _toolbarName, "", "")
  22:  
  23:         btn.BeginsGroup = True
  24:         ' if we like icon + text to appear, uncomment this
  25:         'btn.Text = "OpenDoc"
  26:         btn.Tooltip = _toolTip
  27:         btn.Category = _toolbarName
  28:         btn.Picture = New System.Drawing.Icon(My.Resources.Resource.AppIcon, New System.Drawing.Size(16, 16))
  29:  
  30:         ' initialized to not selected
  31:         _bOpenDoc = False
  32:         tbr = Nothing
  33:         btn = Nothing
  34:     Catch ex As Exception
  35:         g_MapWin.ShowErrorDialog(ex)
  36:     End Try
  37: End Sub
  38:  
  39: Public Sub Terminate() Implements MapWindow.Interfaces.IPlugin.Terminate
  40:     'This event is fired when the user unloads your plug-in either through the plug-in dialog 
  41:     'box, or by un-checkmarking it in the plug-ins menu.  This is where you would remove any
  42:     'buttons from the tool bar tool bar or menu items from the menu that you may have added.
  43:     'If you don't do this, then you will leave dangling menus and buttons that don't do anything.
  44:  
  45:     ' Remove button and the toolbar if plugin is unloaded
  46:     ' Added 04/01/2008 by Earljon Hidalgo
  47:     g_MapWin.Toolbar.RemoveButton(_btnName)
  48:     g_MapWin.Toolbar.RemoveToolbar(_toolbarName)
  49: End Sub
  50:  
  51: Public Sub ItemClicked(ByVal ItemName As String, ByRef Handled As Boolean) Implements MapWindow.Interfaces.IPlugin.ItemClicked
  52:     'This event fires when a menu item or toolbar button is clicked.  So if you added a button or menu
  53:     'on the Initialize event, then this is where you would handle it.
  54:  
  55:     ' Check and save the state of the button
  56:     ' Added 04/01/2008 by Earljon Hidalgo
  57:     Dim bToggle As Boolean = IIf(Not _bOpenDoc, True, False)
  58:     Try
  59:         If ItemName = _btnName Then
  60:             g_MapWin.Toolbar.ButtonItem(_btnName).Pressed = bToggle
  61:             _bOpenDoc = bToggle
  62:             Handled = True
  63:         End If
  64:     Catch ex As System.Exception
  65:         g_MapWin.ShowErrorDialog(ex)
  66:     End Try
  67: End Sub
  68:  
  69: <CLSCompliant(False)> _
  70: Public Sub ShapesSelected(ByVal Handle As Integer, ByVal SelectInfo As MapWindow.Interfaces.SelectInfo) Implements MapWindow.Interfaces.IPlugin.ShapesSelected
  71:     'This event fires when the user selects one or more shapes using the select tool in MapWindow. Handle is the 
  72:     'Layer handle for the shapefile on which shapes were selected. SelectInfo holds information abou the 
  73:     'shapes that were selected. 
  74:     Dim i As Integer
  75:     Dim sf As MapWinGIS.Shapefile
  76:     Dim FileOrURL As String = ""
  77:     Dim newProcess As New Process
  78:     Try
  79:         'make sure something was returned in SelectInfo
  80:         If SelectInfo Is Nothing Then Exit Sub
  81:  
  82:         ' Check the state of the button if we need to open external document
  83:         ' or ignore it
  84:         ' Added 04/01/2008 by Earljon Hidalgo
  85:         If Not _bOpenDoc Then Exit Sub
  86:  
  87:         'get the shapefile object on which a shape was selected
  88:         sf = g_MapWin.Layers(Handle).GetObject
  89:         'Check to see if this shapefile has an attribute field "FileOrURL"
  90:         For i = 0 To sf.NumFields - 1
  91:             If LCase(sf.Field(i).Name) = "fileorurl" Then
  92:                 'This shapefile has the needed attribute field.
  93:                 'We will only be launching one document, so if they selected more than one shape
  94:                 'then we will just launch the document associated with the first selected shape.
  95:                 'Also, i is the index of the field that has the FileOrURL that we are going to 
  96:                 'launch.
  97:                 FileOrURL = sf.CellValue(i, SelectInfo(0).ShapeIndex)
  98:                 Exit For
  99:             End If
 100:         Next
 101:         If FileOrURL <> "" Then
 102:             'Use a .NET process() to launch the file or URL
 103:             MapWinUtility.Logger.Dbg("DocLauncher: Launched File or URL: " + FileOrURL)
 104:             newProcess.StartInfo.FileName = FileOrURL
 105:             newProcess.Start()
 106:         End If
 107:     Catch ex As System.Exception
 108:         MapWinUtility.Logger.Msg(ex.Message)
 109:     End Try
 110: End Sub

When compiled produces this output:

GISMapWindow DocLauncher image

This patch already been uploaded to the SVN repository and hoping to see this changes on the next stable release of GISMapWindow.

SQL Server 2005: Scripting each objects to a separate file

Recently, I decided to set-up a central repository for all our source codes, packages, documents and GIS maps using the open-source Subversion (See my post on this). So after successfully installing the SVN Server, my next task was to commit all SQL scripts to /svn/scripts directory of our repository. And at the moment I thought, how should I generate all the sql scripts in their own file? Before, I was used to just generating sql scripts (tables, stored procedures, views, udf’s) into a single file on our SQL Server 2000 but haven’t tried separating each script to a file.

Not knowing yet what features holds for SQL Server 2005 Management Studio, I immediately look into using EMS products and ApexSQL Script. The EMS doesn’t have the feature to extract all objects into separate files (not that I’m aware of). And for ApexSQL Script, they do have this feature but we don’t have this software but wonderful product indeed based on the listed features on their website.

I googled and it linked my query to Microsoft site What’s New in SQL Server 2005 SP2.

It states under Scripting:
Generate Script Wizard. You can now specify that the scripted objects include a DROP statement before the CREATE statement.  Scripting of objects into separate files is now possible. This feature is supported in SQL Server 2005 Express Edition SP2.

Whoa! What a relief! The SP2 version is now support this feature, so I immediately run and check to see if my SQLExpress is on SP2:

   1: select serverproperty('productlevel')
The query returns SP2.

I then fired-up Management Studio, connect to my existing database and click the Generate scripts submenu:

SQLExpress Generate Script image

On the next window, Select Database appears, if you’re like me that needs to generate all existing scripts on my database, you can check to enable Script all objects in the selected database. As seen on the red circled:

SQLExpress Select Database window image

On the Script Options Window, I set the circled items to False coz I don’t need them enabled and appear on all my scripts.

SQLExpress Script Options Window image

After clicking Next, the Output Options Window displayed, this is the window that allows you to select the files to generate, either by Single file or File per object. I selected the latter coz this is what I wanted and browse my folder to a location on which the generated files will be placed. On the Save As option, I selected the ANSI text for the reason that the produced .sql file will be treated as text/plain and not as a mime-type: binary object of TortoiseSVN client. This will allow us to view the contents of our SQL script source codes via WebSVN (See separate post on how I install WebSVN on both Windows 2003 Server and Ubuntu 7.10 Server) and not to download as default behavior for binary objects.

sql_image4

If your file will be uploaded to your SVN repository and to be viewed online, I suggest reading this post (to be posted soon) to format binary to plain text.

Back to SQL window, clicking Next or Finish will give you the Script Wizard Summary. On this window, you can review the items that the Script Wizard will do.

SQLExpress Script Wizard Summary image

Click Finish and generation of scripts will commence.

SQLExpress Generate Progress image

The generated files will look similar like this:

SQLExpress Generated files image

The filename that was created is the actual name of the SQL object followed by the object type (User, View, Table, Stored Procedure, Schema, User Defined Function and Role) to easily identify what contents the file will have.

If you’re like me and like to remove the type added by SQL Script on the file generated, please read my post (to be posted soon) )on how I removed those extras by doing a batch rename trick.

Extension Method: Check Mobile Number

As a mobile developer for .Net solutions, I often encounter the need to validate the mobile number of a subscriber if it conforms to the correct format. More often, I always create a utility class to do the validation.

One thing I learned from using the latest .NET 3.5 Framework is Extension Method.

So, the way I enable my program to use extension method is as follows:

Method 1:
via the old way:

   1: using System.Text.RegularExpressions;
   2:  
   3: namespace MyConsoleTester
   4: {
   5:     class Utils
   6:     {
   7:         public static bool IsValidMobile(string number)
   8:         {
   9:             bool bFound = false;
  10:             try
  11:             {
  12:                 bFound = Regex.IsMatch(number, @"\A\+\b(639)[012]{1}[0-9]{1}[0-9]{3}[0-9]{4}\b\Z");
  13:             }
  14:             catch (ArgumentException)
  15:             {
  16:  
  17:             }
  18:  
  19:             return bFound;
  20:         }
  21:     }
  22: }

and the implementation would be:

   1: string number = "+639303782321";
   2: bool numValid = Utils.IsValidMobile(number);
   3: Console.WriteLine("Is {0} valid? {1}", number, numValid);

Method 2:
via extension method offers much better and cleaner:

   1: using System.Text.RegularExpressions;
   2:  
   3: namespace MyConsoleTester
   4: {
   5:     public static class SampleExtensions
   6:     {
   7:         public static bool IsValidMobile(this string number)
   8:         {
   9:             bool bFound = false;
  10:             try
  11:             {
  12:                 bFound = Regex.IsMatch(number, @"\A\+\b(639)[012]{1}[0-9]{1}[0-9]{3}[0-9]{4}\b\Z");
  13:             }
  14:             catch (ArgumentException)
  15:             {
  16:                 
  17:             }
  18:  
  19:             return bFound;
  20:         }
  21:     }
  22: }

and the implementation would be as beautiful as this:

   1: using MyConsoleTester;
   2:  
   3: Console.WriteLine("Valid Mobile: +639203782321:\t{0}", "+639303782321".IsValidMobile());

This extension method also posted in ExtensionMethod.net

Windows Live Writer signing in!

As I am starting this blog, I think of a better way to write fast a blog entry without even logging to my WordPress account.

Enter Windows Live Writer.

From LiveWriter:
Writer is an application that makes it easy to publish rich content to your blog

I downloaded this free application from Microsoft just after I created a free account (for now) to WordPress.com. The installation took less than 3 minutes and voila, I can now sign-in and start writing. I even downloaded some of the plugins and will try them out in the near future.

For now, I simply enjoying the benefits of having to write through this.

My version is 2008 Build 12.0