Tuesday 24 November 2015

Decrypting and encrypting messages with gpg in linux (ubuntu)

Encrypting and decrypting files with gpg tool is quite easy:
>gpg --recipient Ben --encrypt test.txt
>gpg --decrypt test.txt.gpg

But if you don't want to create a file and just need to encrypt or decrypt a message quickly?

This workflow will work

Encrypt with your gpg key for some known recipient:
>gpg --armor --encrypt --recipient bend
It might prompt you to type a password for your key at this stage.
Now type your message in and here goes the tick: press CTRL+D, which means the end of a input!
After that it will print your encrypted message into standard output.
Shortcut for the command above:
>gpg --aer bend

Encrypt symmetrically with some passphrase:
>gpg --armor --symmetric
It will prompt you to type a passphrase for symmetric encryption
Now type your message in and press CTRL+D
Shortcut:
>gpg -ac

Decrypt some pgp message:
>gpg --decrypt
Paste your pgp message, for example:
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1

jA0EAwMC1c4w0+3hgT9gySDDFx7lNx0Jwf3aGOwQ8yQc6KKWjnew6LkdtEg3mhOS
bQ==
=7kxT
-----END PGP MESSAGE-----
Type your passphrase (for example 123 for this symmetric message) or a password to your gpg key if it is encrypted for you as a recipient.
And again press CTRL+D to see decrypted message.

Monday 19 October 2015

Practical generic types Contravariant and Covariant subtyping in Scala

I only found one good and simple explanation of generics Contravariance in Julien Richard-Foy’s blog:
http://julien.richard-foy.fr/blog/2013/02/21/be-friend-with-covariance-and-contravariance/

However it was not clear enough for me to memorize all these details, so I decided to develop the idea in a bit different key.

Let’s define some classification of animals:


Covariance
The easy example of covariance is a group of animals of the same kind (flock, heard, whatever...)
So the group of cows is also a group of ungulate, which is group of mammals, whch is a also group of animals:
Cow -> Ungulate -> Mammal -> Animal
Group[Cow] -> Group[Ungulate] -> Group[Mammals] -> Group[Animals]

This is covariance where Cow is a subclass of Animal, the Group[of Cow] is a (subtype of) Group[of Animal]

Contravariance
Imagine that there’s a law describing Veterinary licensing. The law defines the hierarchy of animal classes as above.
The imaginable law states that a Veterinarian with a license of some class is allowed to treat animals of subclasses of this class of animals, therefore:

LicensedVet[for Cows] can only treat Cows
LicensedVet[for Cattle] can only treat Sheep and Cows
LicensedVet[for Mammals] can only treat Dogs, Cats, Sheep and Cows
LicensedVet[for Animals] can treat anyone from this hierarchy

Cow -> Cattle -> Mammal -> Animal
LicensedVet[Cow] <- LicensedVet[Ungulate] <- LicensedVet[Mammal] <- LicensedVet[Animals]

This is contravariance here: Cow is a subclass of Animal, but LicensedVeterinarian[for cows] is not a (subtype of)  LicensedVeterinarian[for all Animals], however the LicensedVeterinarian[for Animals] is a (kind of subtype of) LicensedVeterinarian[for Cows].

This is a practical example of contravariance “from the real life” with kind of practical application.

Ok, let’s do some coding (in Scala):
class Animal(val name: String) {
  override def toString = this.getClass.getSimpleName+": "+name
}
class Mammal(name: String) extends Animal(name)
class Dog(name: String) extends Mammal(name)
class Cat(name: String) extends Mammal(name)

class Cattle(name: String) extends Mammal(name)
class Sheep(name: String) extends Cattle(name)
class Cow(name: String) extends Cattle(name)

class Bird(name: String) extends Animal(name)
class Goose(name: String) extends Bird(name)
class Chicken(name: String) extends Bird(name)

class GroupOfAnimals[A](val list: List[A]) {
  def getOne = list.head
  def getByName(name: String) = list.find({
      case p: Animal if p.name == name => true      case _ => false    }
  )
}

class LicensedVeterinarian[A] {
  def treat(a: A) = {
    print("Treat animal ")
    print(a)
  }
}

val dorothySheep = new Sheep("Dorothy")
val murkaCow = new Cow("Murka")
val gavCat = new Dog("Gav")
val unnamedHen = new Chicken("Hen")

val flockOfSheep = new GroupOfAnimals[Sheep](List(dorothySheep))
val someCattle = new GroupOfAnimals[Cattle](List(murkaCow, dorothySheep))

val jamesHerriot = new LicensedVeterinarian[Animal]
val bobbySmith =  new LicensedVeterinarian[Cattle]

flockOfSheep.getOne //Sheep: Dorothy
someCattle.getOne //Cow: Murka
someCattle.getByName("Murka") //Some(Cow: Murka)

//mr. Herriot can treat anyone
jamesHerriot.treat(dorothySheep)
jamesHerriot.treat(gavCat)
jamesHerriot.treat(unnamedHen)
//Bobby licensed only for Cattle
bobbySmith.treat(dorothySheep)
//bobbySmith.treat(gavCat) //type mismatch, expected: Cattle, actual: Cat
//bobbySmith.treat(unnamedHen) //expected: Cattle, actual: Chicken

Everything seems to work as expected, what for do we need all this covariance and contravariance things?

Imagine that vet can treat a group of animals:
class LicensedVeterinarian[A] {
  def treat(a: A) = {
    print("Treat animal ")
    print(a)
  }
  def treatGroupOfAnimals(g: GroupOfAnimals[A]) = {
    print("Treat animals ")
    print(g)
  }
}
jamesHerriot.treatGroupOfAnimals(someCattle)

If we try to compile the code with James Herriot doing treatGroupOfAnimals compiler will sipt something like:
type mismatch, expected: GroupOfAnimal[Animal], actual: GroupOfAnimal[Cattle]

What? A flock of cattle is not a group of animals? It happens because parametrized types are non-variant by default, so we must define whether it Covariant or Contravariant, otherwise it is considered to be non-variant.

Group of animals is covariant to animals, as mentioned above. So, if we redefine group of animals as follows, James Herriot will be able to treat a group of animals:
class GroupOfAnimals[+A](val list: List[A]) {
  def getOne = list.head
  def getByName(name: String) = list.find({
      case p: Animal if p.name == name => true      case _ => false    }
  )
}
jamesHerriot.treatGroupOfAnimals(someCattle) //now works as expected

Ok. What’s the use for contravariance? Let’s imagine that we have a farm:
object Farm {
  // This one will not work without covariance of GroupOfAnimals
  def areAnimalsOk(group: GroupOfAnimals[Mammal]): Boolean = {
    // Dunno am not a vet, they're always lookin fine
    true
  }
  def inviteVetForCattle(veterinarian: LicensedVeterinarian[Cattle]): Unit = {
    println("Inviting veterinarian for cattle")
  }
  def inviteVetForDog(veterinarian: LicensedVeterinarian[Dog]): Unit = {
    println("Inviting veterinarian for dog")
  }
  def inviteVetForBirds(veterinarian: LicensedVeterinarian[Bird]): Unit = {
    println("Inviting veterinarian for birds")
  }
}
Farm.areAnimalsOk(flockOfSheep) //True: They are always OK
Farm.inviteVetForCattle(bobbySmith)
// ^ This one is OK, Bobby is veterinarian for Cattle
Farm.inviteVetForCattle(jamesHerriot)
//expected:LicensedVeterinarian[Cattle],actual:LicensedVeterinarian[Animal]
Weird! Bobby can be invited to treat Cattle, but James Herriot cannot. As we said above, licensed veterinarians are contravariant to animals, so let’s try make them contravariant:
class LicensedVeterinarian[-A] {
  def treat(a: A) = {
    print("Treat animal ")
    print(a)
  }
  def treatGroupOfAnimals(g: GroupOfAnimals[A]) = {
    print("Treat animals ")
    print(g)
  }
}
Farm.inviteVetForCattle(jamesHerriot)

Phew… With contravariance option we can invite James Herriot. Our farm is safe now.

The final code:
class Animal(val name: String) {
  override def toString = this.getClass.getSimpleName+": "+name
}
class Mammal(name: String) extends Animal(name)
class Dog(name: String) extends Mammal(name)
class Cat(name: String) extends Mammal(name)

class Cattle(name: String) extends Mammal(name)
class Sheep(name: String) extends Cattle(name)
class Cow(name: String) extends Cattle(name)

class Bird(name: String) extends Animal(name)
class Goose(name: String) extends Bird(name)
class Chicken(name: String) extends Bird(name)

class GroupOfAnimals[+A](val list: List[A]) {
  def getOne = list.head
  def getByName(name: String) = list.find({
      case p: Animal if p.name == name => true      case _ => false    }
  )
}

class LicensedVeterinarian[-A] {
  def treat(a: A) = {
    print("Treat animal ")
    print(a)
  }
  def treatGroupOfAnimals(g: GroupOfAnimals[A]) = {
    print("Treat animals ")
    print(g)
  }
}

val dorothySheep = new Sheep("Dorothy")
val murkaCow = new Cow("Murka")
val gavCat = new Dog("Gav")
val unnamedHen = new Chicken("Hen")

val flockOfSheep = new GroupOfAnimals[Sheep](List(dorothySheep))
val someCattle = new GroupOfAnimals[Cattle](List(murkaCow, dorothySheep))

val jamesHerriot = new LicensedVeterinarian[Animal]
val bobbySmith =  new LicensedVeterinarian[Cattle]

flockOfSheep.getOne //Sheep: Dorothy
someCattle.getOne //Cow: Murka
someCattle.getByName("Murka") //Some(Cow: Murka)

//mr. Herriot can treat anyone
jamesHerriot.treat(dorothySheep)
jamesHerriot.treat(gavCat)
jamesHerriot.treat(unnamedHen)
//Bobby licensed only for Cattle
bobbySmith.treat(dorothySheep)
//bobbySmith.treat(gavCat) //type mismatch, expected: Cattle, actual: Cat
//bobbySmith.treat(unnamedHen) //expected: Cattle, actual: Chicken
jamesHerriot.treatGroupOfAnimals(someCattle)

object Farm {
  // This one will not work without covariance of GroupOfAnimals
  def areAnimalsOk(group: GroupOfAnimals[Mammal]): Boolean = {
    // Dunno am not a vet, they're always lookin fine
    true
  }
  def inviteVetForCattle(veterinarian: LicensedVeterinarian[Cattle]): Unit = {
    println("Inviting veterinarian for cattle")
  }
  def inviteVetForDog(veterinarian: LicensedVeterinarian[Dog]): Unit = {
    println("Inviting veterinarian for dog")
  }
  def inviteVetForBirds(veterinarian: LicensedVeterinarian[Bird]): Unit = {
    println("Inviting veterinarian for birds")
  }
}

Farm.areAnimalsOk(flockOfSheep)
Farm.inviteVetForCattle(bobbySmith)
Farm.inviteVetForCattle(jamesHerriot) 
Farm.inviteVetForDog(jamesHerriot)
Farm.inviteVetForBirds(jamesHerriot)
//Bobby is only licensed for cattle, not for birds or dogs:
//Farm.inviteVetForDog(bobbySmith) // Nope, type mismatch
//Farm.inviteVetForBirds(bobbySmith // Nope, type mismatch



Friday 2 October 2015

Sequence of cases in scala

 There's not much said about sequences of cases (sequence of cases) in the "Programming in Scala: second edition". Googling returns a bit different stuff. Essentially they are just more concise way to define match cases and they not only work with Option, but with any other types as well. The code below can describe usage of sequences of cases:

var capitals = Map("France"->"Paris", "Japan"->"Tokyo", "Russia"->"Moscow")

/* sequence of cases */
val withDefaultSequenceOfCases: Option[String] => String = {
  case Some(x) => x // pattern match to extract string from Some
  case None => "?"
}// withDefaultSequenceOfCases: Option[Int] => Int = <function1>

/* match representation of sequence of cases */
def withDefaultMatch(s: Option[String]): String = s match {
  case Some(x) => x
  case None => "?"
}// withDefaultMatch: Option[String] => String = <function1>

capitals get "Russia" //res0: Option[String] = Some(Moscow)
capitals get "Sumatra" //Option[String] = None
capitals("Russia") //String = Moscow
withDefaultSequenceOfCases(Some("Test")) //String = Test
withDefaultSequenceOfCases(capitals get "Japan") //String = Tokyo
withDefaultMatch(capitals get "France") //String = Paris
withDefaultSequenceOfCases(capitals get "Somewhere") //String = ?
withDefaultMatch(capitals get "Pacific") //String = ?

/* sequence of cases is not necessarily Option */
abstract class Expr
case class Number(num: Double) extends Expr
case class UnOp(operator: String, arg: Expr) extends Expr

val renderUnary: Expr => String = {
  case UnOp(op, arg:Number) => op+""+arg.num
  case UnOp(op, arg) => op+""+arg
  case _ => "non unary operator"
}

renderUnary(UnOp("-",Number(1))) //String = -1.0
renderUnary(UnOp("+",Number(2))) //String = +2.0
renderUnary(Number(1)) //String = not unary operator

Tuesday 15 September 2015

Explaining closure pattern name

Live and learn. Indeed.

I'm currently reading a book about Scala and found that "closure" "design pattern" which I've been using in JavaScript for ages is actually from functional programming world, and this closure is not a whole thing, but a variable closing so called "open term".

Imagine the function:
function myFunc(a) {
  return a + b
}

The "a" variable here is a "bound variable", and it makes sense in context of myFunc. The "b" variable is a "free variable" and it is senseless in this context. The "a + b" expression here is an "open term". On the other hand if we replace the expression in myFunc with something like "a + 2" it will be a "closed term".

The name "closure" arises from the act of "closing" the function literal with the open term(s) by "capturing" bindings of its free variables.

var b = 2 //this b variable is actually a closure!
function myFunc(a) {
  return a + b
}

That's it. This variable is the "closure". And the thing is the "function literal" with the "open term".

Tuesday 25 August 2015

String manipulations

One my friend asked me how to memorize these string manipulation functions in most of modern programming languages. Why the hek first argument in substring is zero based and second one is one based?

Everything will be easier if you realize that these offsets are not characters but something between characters. Imagine that characters in your string are separated by lines, and numbers are actually indexes of these separators rather than indexes of characters. The picture below will illustrate it well:



So, when you say “substring”, you ask computer to take a string between these separators and (a – b) will be amount of numbers to substring. If a==b, then you substring zero characters. The same about functions like insert, it inserts a string onto the separator, because you usually need to insert the string between characters, not onto them.

Monday 17 August 2015

Reading XLSX on Android 5+

New Android Build Tools (21+) and Android 5 (ART) seems to easily fix the problem with 65K methods for Apache POI.

All you need to do is to copy the following files into libs dir of your project:
poi-3.12-20150511.jar
poi-ooxml-3.12-20150511.jar
poi-ooxml-schemas-3.12-20150511.jar
stax-1.2.0.jar
stax-api-1.0.1.jar
xmlbeans-2.6.0.jar - the hero of the day, this jar is deffective in maven repo, so it's needed to repack this jar.

See also the repo with repacked POI 3.12 jars and gradle config examples: https://github.com/andruhon/android5xlsx


Add the following into your app/build.gradle to compile your project with multi-dex to fix 65K method's limit and --core-library, to avoid the warning about javax namespace in your libs.
apply plugin: 'com.android.application'

android {
    // ...your other project settings...
    project.tasks.withType(com.android.build.gradle.tasks.Dex) {
        additionalParameters=['--core-library']
    }
}
dependencies {
    // ...deps settings...
    compile 'com.android.support:multidex:1.0.0' //enable multi-dex
}

You still might want to do a 'aavax' hack, to avoid conflicts with future android releases.

If xmlbeans not broken it would be possible to achieve the same results with just adding 'org.apache.poi:poi-ooxml:3.12' into dependencies, however it will not work straighforwardly because xmlbeans jar in maven is defective and contains duplicates of classes, these duplicates are ok for desktop JVM, but android chokes with them. So it is required to add some routine to re-pack xmlbeans and disable preDex. It will work. however the build process will be quite slow, so it is easier just to prepare jars once and put them into libs directory (as described above)

Special thanks to Heiko Johann for pointing onto new Android Build Tools features

Links:
https://github.com/andruhon/android5xlsx - config example
https://developer.android.com/tools/revisions/build-tools.html
https://developer.android.com/tools/building/multidex.html
http://www.docx4java.org/trac/docx4j - another project of reading OpenXML from Java

Previous posts:
http://blog.kondratev.pro/2014/08/reading-xlsx-on-android.html
http://blog.kondratev.pro/2014/09/further-to-my-post-from-yesterday-on.html
http://blog.kondratev.pro/2014/09/reading-xlsx-on-android-3.html

Saturday 25 July 2015

Calculate particular weekdays in the range of dates in JavaScript

I've created a plugin for Moment JS to calculate particular weekdays in the range of dates:
https://github.com/andruhon/moment-weekday-calc

For example it would work if you need to calculate quantity business days in current financial year. The exclusion option to mind public holidays is also available.

The plugin is available in Bower and NPM as moment-weekday-calc.
npm install moment-weekday-calc
bower install moment-weekday-calc

Thursday 25 June 2015

A little bit more on git reset and checkout

HEAD Index Workdir WD Safe?
Commit Level
reset --soft [commit] REF NO NO YES
reset [commit] REF YES NO YES
reset --hard [commit] REF YES YES NO
checkout [commit] HEAD YES YES YES
File Level
reset (commit) [file] NO YES NO YES
checkout (commit) [file] NO YES YES NO
*WD Safe means that this action will not affect files in the workdir

The order of underlying actions on HEAD, index and workdir is the following:
The reset command overwrites these three trees in a specific order,
stopping when you tell it to:
  Move the branch HEAD points to (stop here if --soft)
  Make the Index look like HEAD (stop here unless --hard)
  Make the Working Directory look like the Index

git reset file - is actually a shortcut for git reset --mixed HEAD file and does essentially unstage

Discrard all local commits on master:
git fetch --all
git log origin/master
to find the latest commit on the remote, and
git reset --hard c0mm1tID
to reset down to this commit


Source:

This presentation might also be helpful to quicly review some interesting git features:

Thursday 16 April 2015

Redirect user directly from a webpage to a cordova / phonegap app

There's a Cordova/Phonegap plugin to define custom schemes:
>cordova plugin add https://github.com/EddyVerbruggen/LaunchMyApp-PhoneGap-Plugin.git --variable URL_SCHEME=mycoolapp

The plugin will automatically update a platform config when the platform added or updated.

With this plugin installed custom scheme URLs like two below will invoke the application:
mycoolapp://
mycoolapp://testscreen

It is also possible to handle these URLs in your hybrid app. The handleOpenURL is called when the application is invoked via the custom scheme
/**
 * Custom schema launch plugin callback
 * @param url
 */
var handleOpenURL = function(url) {
    //your code to process the url
};

The example with AngularJS redirecting user to some particular screen of app:
/**
 * Custom schema launch plugin callback
 * @param url
 */
var handleOpenURL = function(url) {
  setTimeout(function(){
    var hash = url.replace("slingshotapp://","");
    var body = document.getElementById("mySlingshotApp");
    var app = angular.element(body);
    var $injector = app.injector();
    var $scope = app.scope();
    var $location = $injector.get('$location');
    $location.path('/'+hash);
    $scope.$apply();
  },300);
};

Please notice that if you install the plugin with the --save flag it will save the URL_SCHEME variable as `prop`, but it should be saved as a `variable` in order to be properly restored on `plugin add` or `update`. Here's the proper feature definition for config.xml:
    <feature name="Custom URL scheme">
        <param name="id" value="nl.x-services.plugins.launchmyapp" />
        <param name="url" value="https://github.com/EddyVerbruggen/LaunchMyApp-PhoneGap-Plugin.git" />
        <variable name="URL_SCHEME" value="mycoolapp" />
    </feature>

Friday 10 April 2015

Invoke phone Dialer from Cordova / Phonegap

There's a "tel:" schema available to invoke an external dialer from the app.

The usage example:
<a href="tel:0-800-202020">0-800-202020</a>

It works in the same way for other schemas such as "mailto:", "sms:", "geo:" and "market:".

To enable this functionality the following access permissions should be added into the config.xml:
<access origin="tel:*" launch-external="yes"/>
<access origin="geo:*" launch-external="yes"/>
<access origin="mailto:*" launch-external="yes"/>
<access origin="sms:*" launch-external="yes"/>
<access origin="market:*" launch-external="yes"/>

Tuesday 31 March 2015

My git cheatsheet


Rebase changes from the master onto current branch

Fetch changes first
git fetch

Rebase
git rebase origin/master

Push
git push origin yourbranchname -f

Branches

Rename/move branch
git branch -m <oldname> <newname>


Tags

Add a tag
git tag -a v1.2 -m 'my annotation for v1.2'

Push the tag:
git push origin v1.2


Diverges
Solutions other than normal merge / mergetool workflow

Hard reset to the origin
git reset --hard origin/branchname

Fixing diverge by deleting branch (loosing you changes)
Checkout master:
git checkout master

Delete diverged branch (dispose all local changes):
git branch -D branchname

Checkout branch back:
git checkout branchname

Fixing diverge by hard reset to some particular commit (loosing you changes)
git reset --hard g00dcmid
assume that you're currently at diverged branch and g00dcmid is a last commit before diverge
please be aware that it will revert all files in the INDEX and in the WORKDIR

Reverts

revert a commit
git revert c0mm1tid
notice, that this will revert this particular commit, not revert to this commit

delete local commits
git reset --hard <commit or branch>

Search

search in commit names
git log --all --grep='some stuff'
--all means - search in all branches

search in patches / diffs (Pickaxe)
git log -S "text to find"
it is also possible to add -p option to list actual diffs

Diffs

show staged diff
git diff --cached

add only non white-space changes
git diff -w --no-color | git apply --cached --ignore-whitespace

Local User
Define a user for single repository:
git config user.email "your@mail.com"
git config user.name "Your Name"

Monday 23 March 2015

Monday 9 March 2015

Sending iOS push notifications from JAVA

This example presumes that you've already registered your device for Push Notifications and retrieved the device token from the Apple Push Notification Service (APNS) on the iOS side.
The code below uses the https://github.com/notnoop/java-apns Java library to send notifications to the APNS server.

The code

Suggested files structure:
src/main/java/PushNotifications.java - simple java class to send notifications
src/main/resources/dev_cert.p12 - development certificate
src/main/resources/prod_cert.p12 - production certificate
pom.xml - maven config

pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>PushNotifications</groupId>
    <artifactId>PushNotifications</artifactId>
    <version>1.0</version>

    <dependencies>
        <dependency>
            <groupId>com.notnoop.apns</groupId>
            <artifactId>apns</artifactId>
            <version>1.0.0.Beta6</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.7</version>
        </dependency>
    </dependencies>

</project>

PushNotifications.java:
import com.notnoop.apns.APNS;
import com.notnoop.apns.ApnsService;
import com.notnoop.apns.ApnsServiceBuilder;

public class PushNotifications {

    public static void main(String [] args) {
        System.out.println("Sending an iOS push notification...");

        String token = "";
        String type = "dev";
        String message = "the test push notification message";

        try {
            token = args[0];
        } catch (Exception e) {
            System.out.println("Usage: PushNotifications devicetoken [message] [type prod|dev]");
            System.out.println("example: PushNotifications 1testdevicetoken3eb414627e78991ac5a615b4a2a95454c6ba5d18930ac137 'hi there!' prod");
            return;
        }
        try {
            message = args[1];
        } catch (Exception e) {
            System.out.println("no message defined, using '"+message+"'");
        }
        try {
            type = args[2];
        } catch (Exception e) {
            System.out.println("no API type defined, using "+type);
        }

        System.out.println("The target token is "+token);

        ApnsServiceBuilder serviceBuilder = APNS.newService();

        if (type.equals("prod")) {
            System.out.println("using prod API");
            String certPath = PushNotifications.class.getResource("prod_cert.p12").getPath();
            serviceBuilder.withCert(certPath, "password")
                    .withProductionDestination();
        } else if (type.equals("dev")) {
            System.out.println("using dev API");
            String certPath = PushNotifications.class.getResource("dev_cert.p12").getPath();
            serviceBuilder.withCert(certPath, "password")
                    .withSandboxDestination();
        } else {
            System.out.println("unknown API type "+type);
            return;
        }

        ApnsService service = serviceBuilder.build();


        //Payload with custom fields
        String payload = APNS.newPayload()
                .alertBody(message)
                .alertTitle("test alert title")
                .sound("default")
                .customField("custom", "custom value").build();

        ////Payload with custom fields
        //String payload = APNS.newPayload()
        //        .alertBody(message).build();

        ////String payload example:
        //String payload = "{\"aps\":{\"alert\":{\"title\":\"My Title 1\",\"body\":\"My message 1\",\"category\":\"Personal\"}}}";


        System.out.println("payload: "+payload);
        service.push(token, payload);

        System.out.println("The message has been hopefully sent...");
    }
}
Compile the code:
>mvn compile

Run the code:
>mvn exec:java -Dexec.mainClass="PushNotifications" -Dexec.args="1testdevicetoken3eb414627e789ba5d18930ac137 'My test iOS push notification!' dev"

Getting certificates from the Apple
Certificates are quite tricky and confusing part of iOS push notifications.

1. First of all we need to create a SigningRequest
Keychain Access -> Certificate Assistant -> Request a certificate from a Certificate Authority
Enter the apple dev email into the Certificate Assistant form, select the "Save to disk" radio
Save the Signing Request onto the disk (don't forget to give it some reasonable name);

2. Go to the developer.apple.com/account/ios/
Certificates, Identifiers & Profiles > App IDs > [the app id] > Edit > Push notifications >
Production SSL Certificate > Create / Create Additional,
ensure that Push Notifications enabled for your app,
Generate a new certificate using the SigningRequest from 1.
Download the generated certificate;

3. (on the Mac) Double click the certificate to import into the keychain;

4. Locate the Certificate in the Keychain Access, expand it to see the Key inside,
right click and Export "keyname"...
Save the p12 file;

5. Notice that after regenerating your certificates you need to refresh your provisioning profiles and use them to deploy your app. In xCode go to Preferences -> Accounts, selet your dev apple-id, click "View Details", do refresh. It is not going to be a problem, if you generated the certeficates before getting to code.

Links
If you use the PHP on you server, you may find the link below useful:
http://www.raywenderlich.com/32960/apple-push-notification-services-in-ios-6-tutorial-part-1

Monday 23 February 2015

Eclipse hotkeys / shortcuts

These are useful shortcuts I always forget after a few weeks not using Eclipse:

Show shortcuts list: ctrl+shift+L

Spellcheck suggestions: ctrl+1
Quick fix suggestions: F2

Rename all occurencies: shift+alt+R
Open resource: ctrl+shift+R
Show Occurrences: ctrl+shift+U
Enable “Block”(rectangle) selection: alt+shift+A
Duplicate Line: ctrl+alt+UP

Select blocks of code: alt+shift+Up (each press selects block one level higher)
De-select blocks of code: alt+shift+Down (each press selects block one level higher)

type hinting (for dynamic typing languages): /* @var $varName \Type */


Preserve case replace:
ctrl+f (edit->find/replace)
tick "Regular expressions" check-box
Find: general
Replace with: \CSeparate

Here \C is a regex retain-case operator it will cause the following results of replacements:
general->separate
General->Separate

Friday 20 February 2015

Get document PDF preview in Alfresco

Alfresco is able to transform document types.
For example transform MSWord doc file into PDF

The quick way to access PDF preview (or of any other available type) is a ThumbnailService

An example:
import org.alfresco.service.cmr.thumbnail.ThumbnailService;
//...
public class YourClass{
  //...
  @Autowired
  ThumbnailService thumbnailService;
  //...
  public yourMethod {
      NodeRef documentNodeRef = new NodeRef(
          request.getParameter("nR")
      );
      NodeRef pdfPreviewNodeRef = null;
      //...
      pdfPreviewNodeRef = thumbnailService.getThumbnailByName(
          documentNodeRef, ContentModel.PROP_CONTENT, "pdf"
      );
      if (pdfPreviewNodeRef==null) {
        //generate a new PDF preview if one is not available yet
        pdfPreviewNodeRef = thumbnailService.createThumbnail(
            documentNodeRef, ContentModel.PROP_CONTENT,
            "application/pdf", new SWFTransformationOptions(), "pdf"
        );
      }
      //...
  }
  //...
}

Wednesday 21 January 2015

A good manual on software versioning

Semantic Versioning: http://semver.org/

Briefly:

Given a version number MAJOR.MINOR.PATCH, increment the:
  1. MAJOR version when you make incompatible API changes,
  2. MINOR version when you add functionality in a backwards-compatible manner, and
  3. PATCH version when you make backwards-compatible bug fixes.
Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.

Wednesday 14 January 2015

Alfresco Javascript webscript Debuggers

Just found that there are actually two of them:

One for the Alfresco repository debugging:
/alfresco/service/api/javascript/debugger
(may be http://127.0.0.1:8080/alfresco/service/api/javascript/debugger)

And one for the Alfresco share debugging:
/share/page/api/javascript/debugger
(may be http://127.0.0.1:8081/share/page/api/javascript/debugger)

Webscript indexes accordingly are:
/alfresco/service/index
(http://127.0.0.1:8080/alfresco/service/index)

and

/share/service/index
(http://127.0.0.1:8081/share/service/index)


Debuggers sometimes won't catch webscripts evaluated: you may need to clean up the project and do "clear dependency caches" and "refresh web scripts" on webscript indexes service pages.