Apache NPanday 1.4.0-incubating released! .NET for Maven

Update: Allthough I still use it (version 1.5.0, not released) NPanday has been retired from Apache Incubator.


It has been a while since the last release now. 1.2.1 was released at Codeplex in September 2010. Late last year we moved the project over to Apache, where we now wait to grow from incubation top-level Apache project.

Now we are pleased to announce our first official release of NPanday under the Apache umbrella!

Info: This post supersedes my post about the withdrawn 1.3-incubating release.

What is NPanday?

NPanday is a tool for build and release management. It brings Maven to .NET (and Mono). It offers a set of plugins to build and test projects, and it defines all the necessary packaging types for deploying and resolving .NET artifacts.

Apache Maven comes with a great infrastructure for dependency management, artifact transport, artifact repositories, release flows with scm-integration, and much more. If you don’t know Maven, go read here. Maven is great!

There is also a Visual Studio 2005/2008/2010 Add-in for English Visual Studio installations.

Why NPanday, now there is NuGet

Wrong question. Competition is great. Sad though, that at least some of the originators for NuGet didn’t even know about Maven and NPanday. NPanday has been around long before NuGet was initialized.

And Maven is an ecosystem grown over almost 10 years. It has much more to offer than auto-download of dependencies. Still I think we need to integrate the dependency-resolving and deployment part with NuGet and NuGet-gallery (See future plans).

What is new in this release?

NPanday now supports .NET 4.0 and Visual Studio 2010. There has also been major internal improvements. The PAB and UAC directories where removed. Now NPanday uses a clean maven local repository. This also removed the necessity for custom additions to the install and deploy phases – which where duplications of the corresponding maven plugins.

In total we resolved 63 issues including many general fixes. Fixes I worked on:

  • NPanday ran all tools from %PATH% instead of the configured Framework. Now the complicated %PATH% setup is not necessary anymore, because NPanday detects installed SDKs and uses the binaries with absolute paths. You’ll only need to have NUnit on the PATH for executing tests.

    This also included:

    • Better detection of installed SDKs.
    • Better handling for executing binaries and projects that contain whitespaces in their path.
  • The compile plug-in did not bind concrete versions of other NPanday plugins, when registering them in the lifecycles. In many cases it was necessary to specify all pug-in’s versions explicitly in a project’s pom. But now, all further plugins are bound to the current version of the compile plug-in in use.
  • Improved Documentation
  • Better committer experience
  • MVN 3-Support
  • Targeting .NET 3.5 without having Compact Framework installed
  • Better exceptions (exposing root causes many places they previously where hidden, removed silent catches)

For more, read the full release notes.

What are the future plans?

On short notice we will release 1.4.1-incubating, containing 14 more issues.

At the same time we are working on version 2.0, which is a huge internal change. NPanday uses a internal RDF database where it keeps additional information for artifacts and depsendencies. This is obsolete, but lots of work to remove.

We also want to lead NPanday to more .NET-like conventions for directory structures i.e., while still maintaining the Maven-influenced layout.  Of course we also try to improve stability, ease of use and documentation.

My agenda for NPanday:

We are 4-5 active committers from which 2 work full-time on NPanday as of today. We would really like to get more committers involved. Find out on how to develop NPanday in the Get Involved Guide.

Where do I get it?

You’ll find everything you need here: NPanday – NPanday Overview

Downloads: NPanday – Download

Current Docs: NPanday – Documentation

Advertisement

Cloning a Slide using Open Xml SDK 2.0

I need to create a presentation with quite recurring contents. So first created a template presentation using Powerpoint. Then I tried to unpack and modify with XSL. I did this with word before, and was quite happy. But for PPTX you have to create two new files per slide. That ended in a mess.

That brought me to the Open Xml SDK 2.0. Still a mess, but it is a little better.

I want to clone a template slide multiple times, and then “inject” my contents into the predefined shapes. That should be easy.

But it took me a while to find out how to correctly clone a slide. So I thought I’d share that with you.

var presentationFile = "SomeFile.pptx";
using (PresentationDocument presentationDocument 
    = PresentationDocument.Open(presentationFile, true))
{
    var presentationPart = presentationDocument.PresentationPart;
    var templatePart = presentationPart.GetSlidePartsInOrder().Last();

    var newSlidePart = templatePart.CloneSlide();

    presentationPart.AppendSlide(newSlidePart);
}

The real code…

… is in this extensions. I created something to find slide parts in the right order, because the order of slide parts stored can be different to the order they appear in. Then I created a utility that clones a slide, and another one that appends the new slide part to the presentation part, which will finally show it.

public static class OpenXmlUtils
{
    public static IEnumerable<SlidePart> GetSlidePartsInOrder(this PresentationPart presentationPart)
    {
        SlideIdList slideIdList = presentationPart.Presentation.SlideIdList;

        return slideIdList.ChildElements
            .Cast<SlideId>()
            .Select(x => presentationPart.GetPartById(x.RelationshipId))
            .Cast<SlidePart>();
    }

    public static SlidePart CloneSlide(this SlidePart templatePart)
    {
        // find the presentationPart: makes the API more fluent
        var presentationPart = templatePart.GetParentParts()
            .OfType<PresentationPart>()
            .Single();

        // clone slide contents
        Slide currentSlide = (Slide)templatePart.Slide.CloneNode(true);
        var slidePartClone = presentationPart.AddNewPart<SlidePart>();
        currentSlide.Save(slidePartClone);

        // copy layout part
        slidePartClone.AddPart(templatePart.SlideLayoutPart);

        return slidePartClone;
    }

    public static void AppendSlide(this PresentationPart presentationPart, SlidePart newSlidePart)
    {
        SlideIdList slideIdList = presentationPart.Presentation.SlideIdList;

        // find the highest id
        uint maxSlideId = slideIdList.ChildElements
            .Cast<SlideId>()
            .Max(x => x.Id.Value);

        // Insert the new slide into the slide list after the previous slide.
        var id = maxSlideId + 1;

        SlideId newSlideId = new SlideId();
        slideIdList.Append(newSlideId);
        newSlideId.Id = id;
        newSlideId.RelationshipId = presentationPart.GetIdOfPart(newSlidePart);
    }
}

The Try/Can-Pattern

I think this is a pattern (repeatedly implemented), although I have not seen it described anywhere yet.

Tell, don’t ask states, that you should trust the code you write. Instead of first asking if “he” can do it, or wants to do it, you just tell “him” to. Instead, it should throw an Exception, if it can’t satisfy the expectations of the caller.

An example for this is Stream.Write(…) or int.Parse(…). If you call the method, you expect it to function. If not, these methods will throw Exceptions.

But what, if you need to check, if a Stream is writable? Or what, if you’d expect the string to be invalid, and you want to respond to that without catching an exception?

This is, where Try/Can is often implemented. Examples for this are Stream.CanWrite, and int.TryParse.

The Try-Part

If it is often the case that a specific command won’t work, you can offer a alternative method that follows this convention:

 

bool TryMethodName(

          [method_parameters,]

          out return_type val)

 

The behavior is specified as follows:

  • TryMethodName should never throw the expected exceptions of  MethodName
  • The original return value should be exposed as an out-parameter.
  • TryMethodName should return a bool, if the operation succeeded or not

This is for example used by the Parse-Method in the .NET BCL:

class Int32 {
  ...
  int Parse(string text);
  bool TryParse(string text, out int val);
  ...
}

OrDefault as a Variation of Try

As a variation of TryMethodName, it can be useful to offer a MethodNameOrDefault. Here, instead of using bool and an output parameter, you’d return the CLR default value of MethodName’s return type, if the expectation stated by MethodName could not be satisfied.

 

return_type MethodNameOrDefault

                ([
method_parameters])

 

OrDefault is heavily used by LINQ:

class Linq.Enumerable {
  ...
  TSource ElementAt<TSource>(
        this IEnumerable<TSource> source, 
        int index);

  TSource ElementAtOrDefault<TSource>(
        this IEnumerable<TSource> source, 
        int index);
  ...
]

The Can-Part

Sometimes, you want to know, if something might work. For example, if you only want to show a button in the UI, if the action potentially can be executed.

 

bool CanMethodName([method_parameters])

// or 

bool CanMethodName { get; }

I’d favor a method over a property. Although a method implies, that it could be expensive to find out if MethodName can, or not.

The behavior is specified as follows:

  • The Can-property or –method should never throw any of the expected exceptions of MethodName
  • It should determine and return, if the method could be executed or if it can’t. Usually a positive return can’t guarantee, that, when really performing the action, it won’t fail.

Can is for example used by System.IO.Stream:

class Stream {
   ...
  int Read(byte[] buffer, int offset, int count);
  bool CanRead { get; }
  ...
}

Summary

Tell, don’t ask! is a very useful principle. It makes code better readable and it helps complying to SRP (Single Responsibility Principle). But sometimes you need more “weak” actions. Try/Can-Pattern helps accomplishing that, while maintaining encapsulation.

I’ll also post some example code on how to implement the pattern in C# soon.