Browse Source

Stubs for language, longurl, shorturl. Some working methods on storage/strategy

Frederic G. MARAND 10 years ago
parent
commit
445b512e0f
9 changed files with 410 additions and 138 deletions
  1. 33 0
      data/db-schema.sql
  2. 3 0
      doc/model.dot
  3. 150 138
      doc/model.svg
  4. 17 0
      kurz.go
  5. 26 0
      storage/language.go
  6. 4 0
      storage/longurl.go
  7. 4 0
      storage/shorturl.go
  8. 31 0
      storage/storage.go
  9. 142 0
      storage/strategy.go

+ 33 - 0
data/db-schema.sql

@@ -0,0 +1,33 @@
+-- phpMyAdmin SQL Dump
+-- version 3.4.10.1deb1
+-- http://www.phpmyadmin.net
+--
+-- Host: localhost
+-- Generation Time: Jan 24, 2015 at 05:32 PM
+-- Server version: 5.5.40
+-- PHP Version: 5.4.36-1+deb.sury.org~precise+2
+
+SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
+SET time_zone = "+00:00";
+
+--
+-- Database: `go_kurz`
+--
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `shorturl`
+--
+
+CREATE TABLE IF NOT EXISTS `shorturl` (
+  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+  `url` varchar(32) NOT NULL COMMENT 'The short URL itself',
+  `domain` int(11) NOT NULL,
+  `strategy` varchar(8) NOT NULL DEFAULT 'base',
+  `submittedBy` int(11) NOT NULL,
+  `submittedInfo` int(11) NOT NULL,
+  `isEnabled` tinyint(1) NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `url` (`url`)
+) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

+ 3 - 0
doc/model.dot

@@ -22,6 +22,9 @@ digraph kurz {
   hit:origin -> eventinfo:k;
   hit:short -> short:k;
 
+  likings:long -> long:k;
+  likings:user -> user:k;
+
   longmeta:info -> eventinfo:k;
   longmeta:language -> language:k;
   longmeta:long -> long:k;

+ 150 - 138
doc/model.svg

@@ -4,211 +4,223 @@
 <!-- Generated by graphviz version 2.26.3 (20100126.1600)
  -->
 <!-- Title: kurz Pages: 1 -->
-<svg width="754pt" height="553pt"
- viewBox="0.00 0.00 754.00 553.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 549)">
+<svg width="762pt" height="676pt"
+ viewBox="0.00 0.00 762.00 676.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 672)">
 <title>kurz</title>
-<polygon fill="white" stroke="white" points="-4,5 -4,-549 751,-549 751,5 -4,5"/>
+<polygon fill="white" stroke="white" points="-4,5 -4,-672 759,-672 759,5 -4,5"/>
 <!-- domain -->
 <g id="node1" class="node"><title>domain</title>
-<polygon fill="none" stroke="black" points="315,-461 315,-539 389,-539 389,-461 315,-461"/>
-<text text-anchor="middle" x="352" y="-522.4" font-family="Times Roman,serif" font-size="14.00">Domain</text>
-<polyline fill="none" stroke="black" points="315,-513 389,-513 "/>
-<text text-anchor="middle" x="352" y="-496.4" font-family="Times Roman,serif" font-size="14.00">owner</text>
-<polyline fill="none" stroke="black" points="315,-487 389,-487 "/>
-<text text-anchor="middle" x="352" y="-470.4" font-family="Times Roman,serif" font-size="14.00">strategy</text>
+<polygon fill="none" stroke="black" points="306,-590 306,-668 380,-668 380,-590 306,-590"/>
+<text text-anchor="middle" x="343" y="-651.4" font-family="Times Roman,serif" font-size="14.00">Domain</text>
+<polyline fill="none" stroke="black" points="306,-642 380,-642 "/>
+<text text-anchor="middle" x="343" y="-625.4" font-family="Times Roman,serif" font-size="14.00">owner</text>
+<polyline fill="none" stroke="black" points="306,-616 380,-616 "/>
+<text text-anchor="middle" x="343" y="-599.4" font-family="Times Roman,serif" font-size="14.00">strategy</text>
 </g>
 <!-- strategy -->
 <g id="node10" class="node"><title>strategy</title>
-<polygon fill="none" stroke="black" points="655.5,-389 655.5,-441 732.5,-441 732.5,-389 655.5,-389"/>
-<text text-anchor="middle" x="694" y="-424.4" font-family="Times Roman,serif" font-size="14.00">Strategy</text>
-<polyline fill="none" stroke="black" points="655.5,-415 732.5,-415 "/>
-<text text-anchor="middle" x="694" y="-398.4" font-family="Times Roman,serif" font-size="14.00">name</text>
+<polygon fill="none" stroke="black" points="663.5,-523 663.5,-575 740.5,-575 740.5,-523 663.5,-523"/>
+<text text-anchor="middle" x="702" y="-558.4" font-family="Times Roman,serif" font-size="14.00">Strategy</text>
+<polyline fill="none" stroke="black" points="663.5,-549 740.5,-549 "/>
+<text text-anchor="middle" x="702" y="-532.4" font-family="Times Roman,serif" font-size="14.00">name</text>
 </g>
 <!-- domain&#45;&gt;strategy -->
 <g id="edge2" class="edge"><title>domain:strategy&#45;&gt;strategy:k</title>
-<path fill="none" stroke="red" d="M389,-474C494.408,-474 522.69,-471.106 624,-442 634.443,-439 638.079,-433.08 644.912,-429.987"/>
-<polygon fill="red" stroke="red" points="645.865,-433.367 655,-428 644.512,-426.499 645.865,-433.367"/>
-<text text-anchor="middle" x="519" y="-478.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
+<path fill="none" stroke="red" d="M380,-603C492.641,-603 523.305,-605.552 632,-576 642.485,-573.149 646.103,-567.164 652.922,-564.023"/>
+<polygon fill="red" stroke="red" points="653.884,-567.399 663,-562 652.507,-560.536 653.884,-567.399"/>
+<text text-anchor="middle" x="527" y="-607.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
 </g>
 <!-- user -->
 <g id="node11" class="node"><title>user</title>
-<polygon fill="none" stroke="black" points="456.5,-247 456.5,-325 581.5,-325 581.5,-247 456.5,-247"/>
-<text text-anchor="middle" x="519" y="-308.4" font-family="Times Roman,serif" font-size="14.00">User</text>
-<polyline fill="none" stroke="black" points="456.5,-299 581.5,-299 "/>
-<text text-anchor="middle" x="519" y="-282.4" font-family="Times Roman,serif" font-size="14.00">language</text>
-<polyline fill="none" stroke="black" points="456.5,-273 581.5,-273 "/>
-<text text-anchor="middle" x="519" y="-256.4" font-family="Times Roman,serif" font-size="14.00">defaultStrategy</text>
+<polygon fill="none" stroke="black" points="464.5,-341 464.5,-419 589.5,-419 589.5,-341 464.5,-341"/>
+<text text-anchor="middle" x="527" y="-402.4" font-family="Times Roman,serif" font-size="14.00">User</text>
+<polyline fill="none" stroke="black" points="464.5,-393 589.5,-393 "/>
+<text text-anchor="middle" x="527" y="-376.4" font-family="Times Roman,serif" font-size="14.00">language</text>
+<polyline fill="none" stroke="black" points="464.5,-367 589.5,-367 "/>
+<text text-anchor="middle" x="527" y="-350.4" font-family="Times Roman,serif" font-size="14.00">defaultStrategy</text>
 </g>
 <!-- domain&#45;&gt;user -->
 <g id="edge4" class="edge"><title>domain:owner&#45;&gt;user:k</title>
-<path fill="none" stroke="red" d="M389,-500C420.114,-500 424.396,-477.983 438,-450 449.831,-425.663 431.061,-338.259 446.902,-316.789"/>
-<polygon fill="red" stroke="red" points="448.781,-319.755 456,-312 445.521,-313.561 448.781,-319.755"/>
-<text text-anchor="middle" x="426" y="-496.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
+<path fill="none" stroke="red" d="M380,-629C431.088,-629 402.899,-569.383 422,-522 432.43,-496.126 436.522,-490.238 446,-464 453.665,-442.779 442.233,-416.507 454.041,-408.458"/>
+<polygon fill="red" stroke="red" points="455.13,-411.794 464,-406 453.453,-404.998 455.13,-411.794"/>
+<text text-anchor="middle" x="434" y="-527.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
 </g>
 <!-- hit -->
 <g id="node2" class="node"><title>hit</title>
-<polygon fill="none" stroke="black" points="5,-259 5,-337 61,-337 61,-259 5,-259"/>
-<text text-anchor="middle" x="33" y="-320.4" font-family="Times Roman,serif" font-size="14.00">Hit</text>
-<polyline fill="none" stroke="black" points="5,-311 61,-311 "/>
-<text text-anchor="middle" x="33" y="-294.4" font-family="Times Roman,serif" font-size="14.00">short</text>
-<polyline fill="none" stroke="black" points="5,-285 61,-285 "/>
-<text text-anchor="middle" x="33" y="-268.4" font-family="Times Roman,serif" font-size="14.00">origin</text>
+<polygon fill="none" stroke="black" points="0,-107 0,-185 56,-185 56,-107 0,-107"/>
+<text text-anchor="middle" x="28" y="-168.4" font-family="Times Roman,serif" font-size="14.00">Hit</text>
+<polyline fill="none" stroke="black" points="0,-159 56,-159 "/>
+<text text-anchor="middle" x="28" y="-142.4" font-family="Times Roman,serif" font-size="14.00">short</text>
+<polyline fill="none" stroke="black" points="0,-133 56,-133 "/>
+<text text-anchor="middle" x="28" y="-116.4" font-family="Times Roman,serif" font-size="14.00">origin</text>
 </g>
 <!-- eventinfo -->
 <g id="node3" class="node"><title>eventinfo</title>
-<polygon fill="none" stroke="black" points="308.5,-127 308.5,-205 395.5,-205 395.5,-127 308.5,-127"/>
-<text text-anchor="middle" x="352" y="-188.4" font-family="Times Roman,serif" font-size="14.00">Event info</text>
-<polyline fill="none" stroke="black" points="308.5,-179 395.5,-179 "/>
-<text text-anchor="middle" x="352" y="-162.4" font-family="Times Roman,serif" font-size="14.00">IP</text>
-<polyline fill="none" stroke="black" points="308.5,-153 395.5,-153 "/>
-<text text-anchor="middle" x="352" y="-136.4" font-family="Times Roman,serif" font-size="14.00">ts</text>
+<polygon fill="none" stroke="black" points="483.5,-0 483.5,-78 570.5,-78 570.5,-0 483.5,-0"/>
+<text text-anchor="middle" x="527" y="-61.4" font-family="Times Roman,serif" font-size="14.00">Event info</text>
+<polyline fill="none" stroke="black" points="483.5,-52 570.5,-52 "/>
+<text text-anchor="middle" x="527" y="-35.4" font-family="Times Roman,serif" font-size="14.00">IP</text>
+<polyline fill="none" stroke="black" points="483.5,-26 570.5,-26 "/>
+<text text-anchor="middle" x="527" y="-9.4" font-family="Times Roman,serif" font-size="14.00">ts</text>
 </g>
 <!-- hit&#45;&gt;eventinfo -->
 <g id="edge6" class="edge"><title>hit:origin&#45;&gt;eventinfo:k</title>
-<path fill="none" stroke="red" d="M61,-272C103.782,-272 87.2826,-219.201 126,-201 196.143,-168.025 224.546,-189.923 297.847,-191.866"/>
-<polygon fill="red" stroke="red" points="297.955,-195.367 308,-192 298.047,-188.368 297.955,-195.367"/>
-<text text-anchor="middle" x="187" y="-206.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
+<path fill="none" stroke="red" d="M56,-120C162.114,-120 177.313,-60.3444 282,-43 335.493,-34.1374 350.277,-35.6592 404,-43 436.444,-47.4332 444.938,-61.6587 472.761,-64.5025"/>
+<polygon fill="red" stroke="red" points="472.842,-68.0105 483,-65 473.182,-61.0187 472.842,-68.0105"/>
+<text text-anchor="middle" x="252" y="-58.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
 </g>
 <!-- short -->
 <g id="node9" class="node"><title>short</title>
-<polygon fill="none" stroke="black" points="134,-337 134,-545 240,-545 240,-337 134,-337"/>
-<text text-anchor="middle" x="187" y="-528.4" font-family="Times Roman,serif" font-size="14.00">Short URL</text>
-<polyline fill="none" stroke="black" points="134,-519 240,-519 "/>
-<text text-anchor="middle" x="187" y="-502.4" font-family="Times Roman,serif" font-size="14.00">value</text>
-<polyline fill="none" stroke="black" points="134,-493 240,-493 "/>
-<text text-anchor="middle" x="187" y="-476.4" font-family="Times Roman,serif" font-size="14.00">shortFor</text>
-<polyline fill="none" stroke="black" points="134,-467 240,-467 "/>
-<text text-anchor="middle" x="187" y="-450.4" font-family="Times Roman,serif" font-size="14.00">domain</text>
-<polyline fill="none" stroke="black" points="134,-441 240,-441 "/>
-<text text-anchor="middle" x="187" y="-424.4" font-family="Times Roman,serif" font-size="14.00">strategy</text>
-<polyline fill="none" stroke="black" points="134,-415 240,-415 "/>
-<text text-anchor="middle" x="187" y="-398.4" font-family="Times Roman,serif" font-size="14.00">submittedBy</text>
-<polyline fill="none" stroke="black" points="134,-389 240,-389 "/>
-<text text-anchor="middle" x="187" y="-372.4" font-family="Times Roman,serif" font-size="14.00">submittedOn</text>
-<polyline fill="none" stroke="black" points="134,-363 240,-363 "/>
-<text text-anchor="middle" x="187" y="-346.4" font-family="Times Roman,serif" font-size="14.00">isEnabled</text>
+<polygon fill="none" stroke="black" points="116,-233 116,-441 222,-441 222,-233 116,-233"/>
+<text text-anchor="middle" x="169" y="-424.4" font-family="Times Roman,serif" font-size="14.00">Short URL</text>
+<polyline fill="none" stroke="black" points="116,-415 222,-415 "/>
+<text text-anchor="middle" x="169" y="-398.4" font-family="Times Roman,serif" font-size="14.00">value</text>
+<polyline fill="none" stroke="black" points="116,-389 222,-389 "/>
+<text text-anchor="middle" x="169" y="-372.4" font-family="Times Roman,serif" font-size="14.00">shortFor</text>
+<polyline fill="none" stroke="black" points="116,-363 222,-363 "/>
+<text text-anchor="middle" x="169" y="-346.4" font-family="Times Roman,serif" font-size="14.00">domain</text>
+<polyline fill="none" stroke="black" points="116,-337 222,-337 "/>
+<text text-anchor="middle" x="169" y="-320.4" font-family="Times Roman,serif" font-size="14.00">strategy</text>
+<polyline fill="none" stroke="black" points="116,-311 222,-311 "/>
+<text text-anchor="middle" x="169" y="-294.4" font-family="Times Roman,serif" font-size="14.00">submittedBy</text>
+<polyline fill="none" stroke="black" points="116,-285 222,-285 "/>
+<text text-anchor="middle" x="169" y="-268.4" font-family="Times Roman,serif" font-size="14.00">submittedOn</text>
+<polyline fill="none" stroke="black" points="116,-259 222,-259 "/>
+<text text-anchor="middle" x="169" y="-242.4" font-family="Times Roman,serif" font-size="14.00">isEnabled</text>
 </g>
 <!-- hit&#45;&gt;short -->
 <g id="edge8" class="edge"><title>hit:short&#45;&gt;short:k</title>
-<path fill="none" stroke="red" d="M61,-298C166.326,-298 34.3982,-516.719 123.969,-531.243"/>
-<polygon fill="red" stroke="red" points="123.765,-534.738 134,-532 124.292,-527.758 123.765,-534.738"/>
-<text text-anchor="middle" x="96" y="-527.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
+<path fill="none" stroke="red" d="M56,-146C180.51,-146 -1.28172,-412.254 105.879,-427.334"/>
+<polygon fill="red" stroke="red" points="105.792,-430.836 116,-428 106.251,-423.851 105.792,-430.836"/>
+<text text-anchor="middle" x="86" y="-430.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
 </g>
 <!-- language -->
 <g id="node4" class="node"><title>language</title>
-<polygon fill="none" stroke="black" points="642.5,-148 642.5,-200 745.5,-200 745.5,-148 642.5,-148"/>
-<text text-anchor="middle" x="694" y="-183.4" font-family="Times Roman,serif" font-size="14.00">Language</text>
-<polyline fill="none" stroke="black" points="642.5,-174 745.5,-174 "/>
-<text text-anchor="middle" x="694" y="-157.4" font-family="Times Roman,serif" font-size="14.00">native name</text>
+<polygon fill="none" stroke="black" points="650.5,-207 650.5,-259 753.5,-259 753.5,-207 650.5,-207"/>
+<text text-anchor="middle" x="702" y="-242.4" font-family="Times Roman,serif" font-size="14.00">Language</text>
+<polyline fill="none" stroke="black" points="650.5,-233 753.5,-233 "/>
+<text text-anchor="middle" x="702" y="-216.4" font-family="Times Roman,serif" font-size="14.00">native name</text>
 </g>
 <!-- likings -->
 <g id="node5" class="node"><title>likings</title>
-<polygon fill="none" stroke="black" points="0,-355 0,-459 66,-459 66,-355 0,-355"/>
-<text text-anchor="middle" x="33" y="-442.4" font-family="Times Roman,serif" font-size="14.00">Likings</text>
-<polyline fill="none" stroke="black" points="0,-433 66,-433 "/>
-<text text-anchor="middle" x="33" y="-416.4" font-family="Times Roman,serif" font-size="14.00">user</text>
-<polyline fill="none" stroke="black" points="0,-407 66,-407 "/>
-<text text-anchor="middle" x="33" y="-390.4" font-family="Times Roman,serif" font-size="14.00">longUrl</text>
-<polyline fill="none" stroke="black" points="0,-381 66,-381 "/>
-<text text-anchor="middle" x="33" y="-364.4" font-family="Times Roman,serif" font-size="14.00">ts</text>
+<polygon fill="none" stroke="black" points="310,-430 310,-534 376,-534 376,-430 310,-430"/>
+<text text-anchor="middle" x="343" y="-517.4" font-family="Times Roman,serif" font-size="14.00">Likings</text>
+<polyline fill="none" stroke="black" points="310,-508 376,-508 "/>
+<text text-anchor="middle" x="343" y="-491.4" font-family="Times Roman,serif" font-size="14.00">user</text>
+<polyline fill="none" stroke="black" points="310,-482 376,-482 "/>
+<text text-anchor="middle" x="343" y="-465.4" font-family="Times Roman,serif" font-size="14.00">longUrl</text>
+<polyline fill="none" stroke="black" points="310,-456 376,-456 "/>
+<text text-anchor="middle" x="343" y="-439.4" font-family="Times Roman,serif" font-size="14.00">ts</text>
 </g>
 <!-- long -->
 <g id="node6" class="node"><title>long</title>
-<polygon fill="none" stroke="black" points="310.5,-348 310.5,-400 393.5,-400 393.5,-348 310.5,-348"/>
-<text text-anchor="middle" x="352" y="-383.4" font-family="Times Roman,serif" font-size="14.00">Long URL</text>
-<polyline fill="none" stroke="black" points="310.5,-374 393.5,-374 "/>
-<text text-anchor="middle" x="352" y="-357.4" font-family="Times Roman,serif" font-size="14.00">value</text>
+<polygon fill="none" stroke="black" points="485.5,-205 485.5,-257 568.5,-257 568.5,-205 485.5,-205"/>
+<text text-anchor="middle" x="527" y="-240.4" font-family="Times Roman,serif" font-size="14.00">Long URL</text>
+<polyline fill="none" stroke="black" points="485.5,-231 568.5,-231 "/>
+<text text-anchor="middle" x="527" y="-214.4" font-family="Times Roman,serif" font-size="14.00">value</text>
+</g>
+<!-- likings&#45;&gt;long -->
+<g id="edge10" class="edge"><title>likings:long&#45;&gt;long:k</title>
+<path fill="none" stroke="red" d="M376,-469C400.698,-469 394.357,-443.737 404,-421 436.393,-344.621 401.588,-251.956 474.976,-244.483"/>
+<polygon fill="red" stroke="red" points="475.18,-247.978 485,-244 474.843,-240.986 475.18,-247.978"/>
+<text text-anchor="middle" x="434" y="-329.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
+</g>
+<!-- likings&#45;&gt;user -->
+<g id="edge12" class="edge"><title>likings:user&#45;&gt;user:k</title>
+<path fill="none" stroke="red" d="M376,-495C427.933,-495 411.114,-417.428 453.915,-407.125"/>
+<polygon fill="red" stroke="red" points="454.45,-410.587 464,-406 453.674,-403.631 454.45,-410.587"/>
+<text text-anchor="middle" x="434" y="-447.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
 </g>
 <!-- longmeta -->
 <g id="node7" class="node"><title>longmeta</title>
-<polygon fill="none" stroke="black" points="126.5,-0 126.5,-156 247.5,-156 247.5,-0 126.5,-0"/>
-<text text-anchor="middle" x="187" y="-139.4" font-family="Times Roman,serif" font-size="14.00">Long metadata</text>
-<polyline fill="none" stroke="black" points="126.5,-130 247.5,-130 "/>
-<text text-anchor="middle" x="187" y="-113.4" font-family="Times Roman,serif" font-size="14.00">longUrl</text>
-<polyline fill="none" stroke="black" points="126.5,-104 247.5,-104 "/>
-<text text-anchor="middle" x="187" y="-87.4" font-family="Times Roman,serif" font-size="14.00">mimeType</text>
-<polyline fill="none" stroke="black" points="126.5,-78 247.5,-78 "/>
-<text text-anchor="middle" x="187" y="-61.4" font-family="Times Roman,serif" font-size="14.00">language</text>
-<polyline fill="none" stroke="black" points="126.5,-52 247.5,-52 "/>
-<text text-anchor="middle" x="187" y="-35.4" font-family="Times Roman,serif" font-size="14.00">imagePath</text>
-<polyline fill="none" stroke="black" points="126.5,-26 247.5,-26 "/>
-<text text-anchor="middle" x="187" y="-9.4" font-family="Times Roman,serif" font-size="14.00">origin</text>
+<polygon fill="none" stroke="black" points="282.5,-52 282.5,-208 403.5,-208 403.5,-52 282.5,-52"/>
+<text text-anchor="middle" x="343" y="-191.4" font-family="Times Roman,serif" font-size="14.00">Long metadata</text>
+<polyline fill="none" stroke="black" points="282.5,-182 403.5,-182 "/>
+<text text-anchor="middle" x="343" y="-165.4" font-family="Times Roman,serif" font-size="14.00">longUrl</text>
+<polyline fill="none" stroke="black" points="282.5,-156 403.5,-156 "/>
+<text text-anchor="middle" x="343" y="-139.4" font-family="Times Roman,serif" font-size="14.00">mimeType</text>
+<polyline fill="none" stroke="black" points="282.5,-130 403.5,-130 "/>
+<text text-anchor="middle" x="343" y="-113.4" font-family="Times Roman,serif" font-size="14.00">language</text>
+<polyline fill="none" stroke="black" points="282.5,-104 403.5,-104 "/>
+<text text-anchor="middle" x="343" y="-87.4" font-family="Times Roman,serif" font-size="14.00">imagePath</text>
+<polyline fill="none" stroke="black" points="282.5,-78 403.5,-78 "/>
+<text text-anchor="middle" x="343" y="-61.4" font-family="Times Roman,serif" font-size="14.00">origin</text>
 </g>
 <!-- longmeta&#45;&gt;eventinfo -->
-<g id="edge10" class="edge"><title>longmeta:info&#45;&gt;eventinfo:k</title>
-<path fill="none" stroke="red" d="M248,-13C266.436,-13 282.61,-151.273 300.498,-184.761"/>
-<polygon fill="red" stroke="red" points="298.373,-187.575 308,-192 303.234,-182.538 298.373,-187.575"/>
-<text text-anchor="middle" x="278" y="-159.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
+<g id="edge14" class="edge"><title>longmeta:info&#45;&gt;eventinfo:k</title>
+<path fill="none" stroke="red" d="M404,-65C435.408,-65 445.744,-65 472.708,-65"/>
+<polygon fill="red" stroke="red" points="473,-68.5001 483,-65 473,-61.5001 473,-68.5001"/>
+<text text-anchor="middle" x="434" y="-70.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
 </g>
 <!-- longmeta&#45;&gt;language -->
-<g id="edge12" class="edge"><title>longmeta:language&#45;&gt;language:k</title>
-<path fill="none" stroke="red" d="M248,-65C256.584,-65 257.89,-69.1873 266,-72 304.857,-85.4772 565.064,-175.498 631.873,-186.001"/>
-<polygon fill="red" stroke="red" points="631.705,-189.501 642,-187 632.392,-182.535 631.705,-189.501"/>
-<text text-anchor="middle" x="426" y="-135.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
+<g id="edge16" class="edge"><title>longmeta:language&#45;&gt;language:k</title>
+<path fill="none" stroke="red" d="M404,-117C419.932,-117 408.948,-138.864 422,-148 484.137,-191.495 523.888,-140.823 590,-178 621.838,-195.903 612.145,-237.205 640.046,-244.791"/>
+<polygon fill="red" stroke="red" points="639.651,-248.269 650,-246 640.495,-241.32 639.651,-248.269"/>
+<text text-anchor="middle" x="527" y="-183.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
 </g>
 <!-- longmeta&#45;&gt;long -->
-<g id="edge14" class="edge"><title>longmeta:long&#45;&gt;long:k</title>
-<path fill="none" stroke="red" d="M248,-117C276.504,-117 259.789,-216.181 266,-244 279.696,-305.349 247.395,-378.497 299.994,-386.314"/>
-<polygon fill="red" stroke="red" points="299.784,-389.808 310,-387 300.263,-382.824 299.784,-389.808"/>
-<text text-anchor="middle" x="278" y="-387.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
+<g id="edge18" class="edge"><title>longmeta:long&#45;&gt;long:k</title>
+<path fill="none" stroke="red" d="M404,-169C425.465,-169 452.6,-226.422 475.483,-240.777"/>
+<polygon fill="red" stroke="red" points="474.406,-244.108 485,-244 476.651,-237.478 474.406,-244.108"/>
+<text text-anchor="middle" x="434" y="-212.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
 </g>
 <!-- session -->
 <g id="node8" class="node"><title>session</title>
-<polygon fill="none" stroke="black" points="153,-228 153,-306 221,-306 221,-228 153,-228"/>
-<text text-anchor="middle" x="187" y="-289.4" font-family="Times Roman,serif" font-size="14.00">Session</text>
-<polyline fill="none" stroke="black" points="153,-280 221,-280 "/>
-<text text-anchor="middle" x="187" y="-263.4" font-family="Times Roman,serif" font-size="14.00">user</text>
-<polyline fill="none" stroke="black" points="153,-254 221,-254 "/>
-<text text-anchor="middle" x="187" y="-237.4" font-family="Times Roman,serif" font-size="14.00">info</text>
+<polygon fill="none" stroke="black" points="309,-334 309,-412 377,-412 377,-334 309,-334"/>
+<text text-anchor="middle" x="343" y="-395.4" font-family="Times Roman,serif" font-size="14.00">Session</text>
+<polyline fill="none" stroke="black" points="309,-386 377,-386 "/>
+<text text-anchor="middle" x="343" y="-369.4" font-family="Times Roman,serif" font-size="14.00">user</text>
+<polyline fill="none" stroke="black" points="309,-360 377,-360 "/>
+<text text-anchor="middle" x="343" y="-343.4" font-family="Times Roman,serif" font-size="14.00">info</text>
 </g>
 <!-- session&#45;&gt;eventinfo -->
-<g id="edge16" class="edge"><title>session:info&#45;&gt;eventinfo:k</title>
-<path fill="none" stroke="red" d="M221,-241C256.01,-241 259.722,-220.577 290,-203 294.054,-200.646 296.21,-197.896 298.525,-195.735"/>
-<polygon fill="red" stroke="red" points="299.98,-198.923 308,-192 297.413,-192.411 299.98,-198.923"/>
-<text text-anchor="middle" x="278" y="-227.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
+<g id="edge20" class="edge"><title>session:info&#45;&gt;eventinfo:k</title>
+<path fill="none" stroke="red" d="M343,-333C343,-305.28 385.396,-340.55 404,-320 428.31,-293.148 409.73,-192.08 422,-158 429.293,-137.743 451.413,-82.2088 473.331,-68.2279"/>
+<polygon fill="red" stroke="red" points="474.623,-71.4866 483,-65 472.406,-64.8469 474.623,-71.4866"/>
+<text text-anchor="middle" x="434" y="-163.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
 </g>
 <!-- session&#45;&gt;user -->
-<g id="edge18" class="edge"><title>session:user&#45;&gt;user:k</title>
-<path fill="none" stroke="red" d="M221,-267C298.81,-267 321.472,-249.643 396,-272 417.028,-278.308 419.976,-285.465 438,-298 442.42,-301.074 444.364,-304.833 446.734,-307.682"/>
-<polygon fill="red" stroke="red" points="445.457,-310.948 456,-312 448.414,-304.603 445.457,-310.948"/>
-<text text-anchor="middle" x="352" y="-277.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
+<g id="edge22" class="edge"><title>session:user&#45;&gt;user:k</title>
+<path fill="none" stroke="red" d="M377,-373C408.693,-373 417.815,-376.507 446,-391 451.065,-393.604 452.859,-397.846 455.148,-401.156"/>
+<polygon fill="red" stroke="red" points="453.547,-404.27 464,-406 456.908,-398.129 453.547,-404.27"/>
+<text text-anchor="middle" x="434" y="-396.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
 </g>
 <!-- short&#45;&gt;domain -->
-<g id="edge20" class="edge"><title>short:domain&#45;&gt;domain:k</title>
-<path fill="none" stroke="red" d="M240,-454C262.505,-454 272.48,-447.875 290,-462 310.245,-478.322 291.994,-513.256 304.988,-523.267"/>
-<polygon fill="red" stroke="red" points="304.431,-526.743 315,-526 306.275,-519.99 304.431,-526.743"/>
-<text text-anchor="middle" x="278" y="-467.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
+<g id="edge24" class="edge"><title>short:domain&#45;&gt;domain:k</title>
+<path fill="none" stroke="red" d="M222,-350C247.191,-350 230.476,-552.679 240,-576 255.879,-614.881 259.668,-648.95 295.573,-654.277"/>
+<polygon fill="red" stroke="red" points="295.782,-657.8 306,-655 296.266,-650.817 295.782,-657.8"/>
+<text text-anchor="middle" x="252" y="-638.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
 </g>
 <!-- short&#45;&gt;long -->
-<g id="edge22" class="edge"><title>short:long&#45;&gt;long:k</title>
-<path fill="none" stroke="red" d="M240,-480C262.222,-480 272.713,-493.964 290,-480 319.548,-456.131 278.019,-400.083 299.939,-388.944"/>
-<polygon fill="red" stroke="red" points="300.846,-392.334 310,-387 299.518,-385.461 300.846,-392.334"/>
-<text text-anchor="middle" x="278" y="-491.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
+<g id="edge26" class="edge"><title>short:long&#45;&gt;long:k</title>
+<path fill="none" stroke="red" d="M222,-376C260.181,-376 218.276,-323.398 240,-292 252.626,-273.751 261.059,-272.342 282,-265 364.335,-236.133 392.177,-243.37 474.908,-243.963"/>
+<polygon fill="red" stroke="red" points="474.987,-247.464 485,-244 475.013,-240.464 474.987,-247.464"/>
+<text text-anchor="middle" x="343" y="-270.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
 </g>
 <!-- short&#45;&gt;strategy -->
-<g id="edge26" class="edge"><title>short:strategy&#45;&gt;strategy:k</title>
-<path fill="none" stroke="red" d="M240,-428C421.022,-428 468.797,-428 644.874,-428"/>
-<polygon fill="red" stroke="red" points="645,-431.5 655,-428 645,-424.5 645,-431.5"/>
-<text text-anchor="middle" x="426" y="-433.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
+<g id="edge30" class="edge"><title>short:strategy&#45;&gt;strategy:k</title>
+<path fill="none" stroke="red" d="M222,-324C322.92,-324 203.312,-479.809 282,-543 345.644,-594.11 561.374,-564.409 652.978,-562.135"/>
+<polygon fill="red" stroke="red" points="653.048,-565.634 663,-562 652.954,-558.635 653.048,-565.634"/>
+<text text-anchor="middle" x="434" y="-577.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
 </g>
 <!-- short&#45;&gt;user -->
-<g id="edge24" class="edge"><title>short:user&#45;&gt;user:k</title>
-<path fill="none" stroke="red" d="M240,-402C275.7,-402 238.237,-348.443 266,-326 278.962,-315.522 292.244,-312.145 445.689,-312.005"/>
-<polygon fill="red" stroke="red" points="446.002,-315.505 456,-312 445.998,-308.505 446.002,-315.505"/>
-<text text-anchor="middle" x="352" y="-319.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
+<g id="edge28" class="edge"><title>short:user&#45;&gt;user:k</title>
+<path fill="none" stroke="red" d="M222,-298C302.988,-298 334.265,-265.817 404,-307 434.587,-325.063 427.746,-344.526 446,-375 451.756,-384.61 450.44,-396.032 454.69,-401.967"/>
+<polygon fill="red" stroke="red" points="453.433,-405.236 464,-406 456.215,-398.813 453.433,-405.236"/>
+<text text-anchor="middle" x="343" y="-312.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
 </g>
 <!-- user&#45;&gt;language -->
-<g id="edge28" class="edge"><title>user:language&#45;&gt;language:k</title>
-<path fill="none" stroke="red" d="M582,-286C601.676,-286 610.895,-286.677 624,-272 646.906,-246.346 612.658,-198.965 632.173,-188.907"/>
-<polygon fill="red" stroke="red" points="632.85,-192.341 642,-187 631.516,-185.47 632.85,-192.341"/>
-<text text-anchor="middle" x="612" y="-290.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
+<g id="edge32" class="edge"><title>user:language&#45;&gt;language:k</title>
+<path fill="none" stroke="red" d="M590,-380C651.43,-380 592.543,-261.243 639.873,-247.326"/>
+<polygon fill="red" stroke="red" points="640.539,-250.769 650,-246 639.63,-243.828 640.539,-250.769"/>
+<text text-anchor="middle" x="620" y="-379.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
 </g>
 <!-- user&#45;&gt;strategy -->
-<g id="edge30" class="edge"><title>user:strategy&#45;&gt;strategy:k</title>
-<path fill="none" stroke="red" d="M582,-260C591.152,-260 591.141,-252.296 600,-250 610.326,-247.324 615.836,-243.135 624,-250 682.58,-299.259 584.704,-416.322 644.93,-427.188"/>
-<polygon fill="red" stroke="red" points="644.751,-430.685 655,-428 645.314,-423.708 644.751,-430.685"/>
-<text text-anchor="middle" x="612" y="-255.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
+<g id="edge34" class="edge"><title>user:strategy&#45;&gt;strategy:k</title>
+<path fill="none" stroke="red" d="M590,-354C600.788,-354 639.71,-515.39 657.201,-553.846"/>
+<polygon fill="red" stroke="red" points="654.352,-555.879 663,-562 660.057,-551.822 654.352,-555.879"/>
+<text text-anchor="middle" x="620" y="-481.4" font-family="Times Roman,serif" font-size="14.00">is a</text>
 </g>
 </g>
 </svg>

+ 17 - 0
kurz.go

@@ -0,0 +1,17 @@
+package main
+
+import (
+	"github.com/FGM/kurz/storage"
+	"github.com/davecgh/go-spew/spew"
+	"log"
+)
+
+func main() {
+	err := storage.Service.Open("someuser:somepass@tcp(localhost:3306)/go_kurz")
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer storage.Service.Close()
+
+	spew.Dump(storage.StrategyStatistics(storage.Service))
+}

+ 26 - 0
storage/language.go

@@ -0,0 +1,26 @@
+package storage
+
+type Language struct {
+	Code   string
+	Native string
+}
+
+var languageMap map[string]string = map[string]string{
+	"de": "Deutsch",
+	"eo": "Esperanto",
+	"en": "English",
+	"fr": "Français",
+}
+
+var Languages map[string]Language
+
+func init() {
+	Languages = make(map[string]Language, len(languageMap))
+
+	for code, native := range languageMap {
+		Languages[code] = Language{
+			Code:   code,
+			Native: native,
+		}
+	}
+}

+ 4 - 0
storage/longurl.go

@@ -0,0 +1,4 @@
+package storage
+
+type LongUrl struct {
+}

+ 4 - 0
storage/shorturl.go

@@ -0,0 +1,4 @@
+package storage
+
+type ShortUrl struct {
+}

+ 31 - 0
storage/storage.go

@@ -0,0 +1,31 @@
+package storage
+
+/**
+TODO use a CLI flag to clear the database on init
+*/
+
+import (
+	"database/sql"
+	_ "github.com/go-sql-driver/mysql"
+	"log"
+)
+
+type Storage struct {
+	Name string
+	DB   *sql.DB
+}
+
+var Service Storage = Storage{}
+
+func (s *Storage) Open(dbName string) error {
+	var err error
+	s.DB, err = sql.Open("mysql", dbName)
+	if err != nil {
+		log.Fatal(err)
+	}
+	return err
+}
+
+func (s *Storage) Close() {
+	s.DB.Close()
+}

+ 142 - 0
storage/strategy.go

@@ -0,0 +1,142 @@
+package storage
+
+import (
+	"database/sql"
+	"errors"
+	"log"
+)
+
+type Strategy interface {
+	Name() string
+	Alias(url LongUrl) (ShortUrl, error)
+	UseCount(storage Storage) int
+}
+
+type baseStrategy struct{}
+
+func (y baseStrategy) Name() string {
+	return "base"
+}
+
+func (y baseStrategy) Alias(long LongUrl) (ShortUrl, error) {
+	var ret ShortUrl
+	var err error = errors.New("Base strategy is abstract")
+
+	return ret, err
+}
+
+/**
+Any nonzero result is likely an error.
+*/
+func (y baseStrategy) UseCount(s Storage) int {
+	sql := `
+SELECT COUNT(*)
+FROM shorturl
+WHERE strategy = ?
+	`
+	var count int
+	err := s.DB.QueryRow(sql, y.Name()).Scan(&count)
+	if err != nil {
+		count = 0
+		log.Printf("Failed querying database for base strategy use count: %v\n", err)
+	}
+
+	return count
+}
+
+/*
+Legacy strategy : hex dump for crc32 hash of source URL.
+
+  - Pros :
+    - URLs are easy to communicate over the phone, especially to programmers, even in poor sound conditions.
+  - Cons :
+    - They are rather long
+    - Does not handle collisions: first come, first serve. Later entries are simply rejected.
+*/
+type HexCrc32Strategy struct {
+	base baseStrategy
+}
+
+func (s HexCrc32Strategy) Name() string {
+	return "hexCrc32"
+}
+
+func (s HexCrc32Strategy) Alias(url LongUrl) (ShortUrl, error) {
+	var ret ShortUrl
+
+	return ret, errors.New("HexCrc32 not implemented yet")
+}
+
+func (y HexCrc32Strategy) UseCount(s Storage) int {
+	return y.base.UseCount(s)
+}
+
+type ManualStrategy struct {
+	base baseStrategy
+}
+
+func (y ManualStrategy) Name() string {
+	return "manual"
+}
+
+func (y ManualStrategy) Alias(long LongUrl) (ShortUrl, error) {
+	var ret ShortUrl
+
+	return ret, errors.New("Manual not implemented yet")
+}
+
+func (y ManualStrategy) UseCount(s Storage) int {
+	return y.base.UseCount(s)
+}
+
+var Strategies map[string]Strategy
+
+func init() {
+	var strategyImplementations []Strategy = []Strategy{
+		baseStrategy{},
+		HexCrc32Strategy{},
+		ManualStrategy{},
+	}
+
+	Strategies = make(map[string]Strategy, len(strategyImplementations))
+	for _, s := range strategyImplementations {
+		Strategies[s.Name()] = s
+	}
+}
+
+func StrategyStatistics(s Storage) map[string]int64 {
+	var ret map[string]int64 = make(map[string]int64, len(Strategies))
+	var err error
+	var strategyResult sql.NullString
+	var countResult sql.NullInt64
+
+	sql := `
+SELECT strategy, COUNT(*)
+FROM shorturl
+GROUP BY strategy
+	`
+
+	rows, err := s.DB.Query(sql)
+	if err != nil {
+		log.Printf("Failed querying database for strategy statistics: %v\n", err)
+	}
+	defer rows.Close()
+	for rows.Next() {
+		if err = rows.Scan(&strategyResult, &countResult); err != nil {
+			log.Fatal(err)
+		}
+		validStrategy, ok := Strategies[strategyResult.String]
+		if !ok {
+			log.Fatalf("'%s' is not a valid strategy\n", strategyResult)
+		}
+		ret[validStrategy.Name()] = countResult.Int64
+	}
+
+	for name, _ := range Strategies {
+		_, ok := ret[name]
+		if !ok {
+			ret[name] = 0
+		}
+	}
+	return ret
+}