├── src ├── handler │ ├── Handler.java │ ├── DecoratingHandler.java │ ├── PrintingHandler.java │ ├── BlockingChannelHandler.java │ ├── ThreadedHandler.java │ ├── TransmogrifyHandler.java │ ├── TransmogrifyChannelHandler.java │ ├── ExecutorServiceHandler.java │ ├── ExceptionHandler.java │ ├── AcceptHandler.java │ ├── ReadHandler.java │ ├── WriteHandler.java │ └── PooledReadHandler.java ├── NastyChump.java ├── util │ └── Util.java └── server │ ├── MultiThreadedBlockingServer.java │ ├── SingleThreadedBlockingServer.java │ ├── ExecutorServiceBlockingServer.java │ ├── BlockingNIOServer.java │ ├── SingleThreadedPollingNonBlockingServer.java │ ├── SingleThreadedSelectorNonBlockingServer.java │ └── SelectorNonBlockingServerWithWorkerPool.java ├── README.md ├── Transmogrifier.iml ├── todo.txt ├── Transmogrifier.iws └── Transmogrifier.ipr /src/handler/Handler.java: -------------------------------------------------------------------------------- 1 | package handler; 2 | 3 | import java.io.*; 4 | 5 | public interface Handler { 6 | public void handle(S s) throws X; 7 | } 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Transmogrifier 2 | Live coding talk by Dr Heinz Kabutz, including threading, design patterns and Java NIO 3 | 4 | See http://www.javaspecialists.eu/tutorials/006.01-Transmogrifier-Java-NIO-and-Non-Blocking-IO--Introduction.html 5 | -------------------------------------------------------------------------------- /src/handler/DecoratingHandler.java: -------------------------------------------------------------------------------- 1 | package handler; 2 | 3 | public abstract class DecoratingHandler implements Handler { 4 | private final Handler other; 5 | 6 | public DecoratingHandler(Handler other) { 7 | this.other = other; 8 | } 9 | 10 | public void handle(S s) throws X { 11 | other.handle(s); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Transmogrifier.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/handler/PrintingHandler.java: -------------------------------------------------------------------------------- 1 | package handler; 2 | 3 | // a decorator 4 | public class PrintingHandler extends DecoratingHandler { 5 | public PrintingHandler(Handler other) { 6 | super(other); 7 | } 8 | 9 | public void handle(S s) throws X { 10 | System.out.println("Connected to " + s); 11 | try { 12 | super.handle(s); 13 | } finally { 14 | System.out.println("Disconnected from " + s); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/handler/BlockingChannelHandler.java: -------------------------------------------------------------------------------- 1 | package handler; 2 | 3 | import java.io.*; 4 | import java.nio.channels.*; 5 | 6 | public class BlockingChannelHandler 7 | extends DecoratingHandler { 8 | 9 | public BlockingChannelHandler(Handler other) { 10 | super(other); 11 | } 12 | 13 | public void handle(SocketChannel sc) throws IOException { 14 | while(sc.isConnected()) { 15 | super.handle(sc); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/handler/ThreadedHandler.java: -------------------------------------------------------------------------------- 1 | package handler; 2 | 3 | import java.util.function.*; 4 | 5 | public class ThreadedHandler extends ExceptionHandler { 6 | public ThreadedHandler(Handler other) { 7 | super(other); 8 | } 9 | 10 | public ThreadedHandler(Handler other, BiConsumer exceptionConsumer) { 11 | super(other, exceptionConsumer); 12 | } 13 | 14 | public void handle(S s) { 15 | new Thread(() -> super.handle(s)).start(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/handler/TransmogrifyHandler.java: -------------------------------------------------------------------------------- 1 | package handler; 2 | 3 | import util.*; 4 | 5 | import java.io.*; 6 | import java.net.*; 7 | 8 | public class TransmogrifyHandler implements Handler { 9 | public void handle(Socket s) throws IOException { 10 | try ( 11 | InputStream in = s.getInputStream(); 12 | OutputStream out = s.getOutputStream() 13 | ) { 14 | int data; 15 | while ((data = in.read()) != -1) { 16 | out.write(Util.transmogrify(data)); 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/NastyChump.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.net.*; 3 | import java.util.concurrent.*; 4 | 5 | public class NastyChump { 6 | public static void main(String... args) throws InterruptedException { 7 | Socket[] sockets = new Socket[3000]; 8 | for (int i = 0; i < sockets.length; i++) { 9 | try { 10 | sockets[i] = new Socket("localhost", 8080); 11 | System.out.println(i); 12 | } catch (IOException e) { 13 | System.err.println("Error connecting " + e); 14 | } 15 | } 16 | TimeUnit.DAYS.sleep(1); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/util/Util.java: -------------------------------------------------------------------------------- 1 | package util; 2 | 3 | import java.nio.*; 4 | 5 | public class Util { 6 | public static int transmogrify(int data) { 7 | return Character.isLetter(data) ? data ^ ' ' : data; 8 | } 9 | 10 | public static void transmogrify(ByteBuffer buf) { 11 | // before reading "hello": pos = 0 limit = 80 capacity = 80 12 | // after reading "hello": pos = 5 limit = 80 capacity = 80 13 | // set pos = 0 and limit = 5 14 | buf.flip(); 15 | for (int i = 0; i < buf.limit(); i++) { 16 | buf.put(i, (byte) transmogrify(buf.get(i))); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/server/MultiThreadedBlockingServer.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import handler.*; 4 | 5 | import java.io.*; 6 | import java.net.*; 7 | 8 | public class MultiThreadedBlockingServer { 9 | public static void main(String... args) throws IOException { 10 | ServerSocket ss = new ServerSocket(8080); 11 | Handler handler = 12 | new ThreadedHandler<>( 13 | new PrintingHandler<>( 14 | new TransmogrifyHandler() 15 | )); 16 | while (true) { 17 | Socket s = ss.accept(); // never null - blocks 18 | handler.handle(s); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /todo.txt: -------------------------------------------------------------------------------- 1 | 0. Who is Heinz Kabutz? 2 | Not Ketchup 3 | Not baked beans 4 | Not a community in Israel 5 | Island of Crete 6 | 36ºC 7 | Java Specialists' Newsletter 8 | www.javaspecialists.eu 9 | 1. Blocking, single-threaded server √ 10 | Design patterns √ 11 | 2. Threaded blocking server √ 12 | 3. Blocking server using executor service √ 13 | 3.1. Fixed vs. Cached √ 14 | 3.2. Job Queue √ 15 | 3.3. Rejected Task Policies √ 16 | 4. Blocking Java NIO Server √ 17 | 5. Simple polling non-blocking NIO Server √ 18 | 6. Single-threaded NIO Server with Selector √ 19 | 7. NIO Server with Selector with pool for tasks √ -------------------------------------------------------------------------------- /src/server/SingleThreadedBlockingServer.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import handler.*; 4 | 5 | import java.io.*; 6 | import java.net.*; 7 | 8 | public class SingleThreadedBlockingServer { 9 | public static void main(String... args) throws IOException { 10 | ServerSocket ss = new ServerSocket(8080); 11 | Handler handler = 12 | new ExceptionHandler<>( 13 | new PrintingHandler<>( 14 | new TransmogrifyHandler() 15 | )); 16 | while (true) { 17 | Socket s = ss.accept(); // never null - blocks 18 | handler.handle(s); 19 | s.close(); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/handler/TransmogrifyChannelHandler.java: -------------------------------------------------------------------------------- 1 | package handler; 2 | 3 | import util.*; 4 | 5 | import java.io.*; 6 | import java.net.*; 7 | import java.nio.*; 8 | import java.nio.channels.*; 9 | 10 | public class TransmogrifyChannelHandler implements Handler { 11 | public void handle(SocketChannel sc) throws IOException { 12 | ByteBuffer buf = ByteBuffer.allocateDirect(80); 13 | int read = sc.read(buf); 14 | if (read == -1) { 15 | sc.close(); 16 | return; 17 | } 18 | if (read > 0) { 19 | Util.transmogrify(buf); 20 | while(buf.hasRemaining()) { 21 | sc.write(buf); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/handler/ExecutorServiceHandler.java: -------------------------------------------------------------------------------- 1 | package handler; 2 | 3 | import java.util.concurrent.*; 4 | import java.util.function.*; 5 | 6 | public class ExecutorServiceHandler extends ExceptionHandler { 7 | private final ExecutorService pool; 8 | 9 | public ExecutorServiceHandler(ExecutorService pool, Handler other) { 10 | super(other); 11 | this.pool = pool; 12 | } 13 | 14 | public ExecutorServiceHandler(ExecutorService pool, Handler other, BiConsumer exceptionConsumer) { 15 | super(other, exceptionConsumer); 16 | this.pool = pool; 17 | } 18 | 19 | public void handle(S s) { 20 | pool.submit(() -> super.handle(s)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/handler/ExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package handler; 2 | 3 | import java.util.function.*; 4 | 5 | // another decorator 6 | public class ExceptionHandler extends DecoratingHandler { 7 | private final BiConsumer exceptionConsumer; 8 | 9 | public ExceptionHandler(Handler other, BiConsumer exceptionConsumer) { 10 | super(other); 11 | this.exceptionConsumer = exceptionConsumer; 12 | } 13 | 14 | public ExceptionHandler(Handler other) { 15 | this(other, (s, x) -> System.err.println("Issue with " + s + " error " + x)); 16 | } 17 | 18 | public void handle(S s) { 19 | try { 20 | super.handle(s); 21 | } catch (Throwable x) { 22 | exceptionConsumer.accept(s, x); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/server/ExecutorServiceBlockingServer.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import handler.*; 4 | 5 | import java.io.*; 6 | import java.net.*; 7 | import java.util.concurrent.*; 8 | 9 | public class ExecutorServiceBlockingServer { 10 | public static void main(String... args) throws IOException { 11 | ServerSocket ss = new ServerSocket(8080); 12 | ExecutorService pool = new ThreadPoolExecutor( 13 | 10, 100, 14 | 0L, TimeUnit.MILLISECONDS, 15 | new LinkedBlockingQueue(1000)); 16 | Handler handler = 17 | new ExecutorServiceHandler( 18 | pool, 19 | new PrintingHandler<>( 20 | new TransmogrifyHandler() 21 | )); 22 | while (true) { 23 | Socket s = ss.accept(); // never null - blocks 24 | handler.handle(s); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/handler/AcceptHandler.java: -------------------------------------------------------------------------------- 1 | package handler; 2 | 3 | import java.io.*; 4 | import java.nio.*; 5 | import java.nio.channels.*; 6 | import java.util.*; 7 | import java.util.concurrent.*; 8 | 9 | public class AcceptHandler implements Handler { 10 | private final Map> pendingData; 11 | 12 | public AcceptHandler(Map> pendingData) { 13 | this.pendingData = pendingData; 14 | } 15 | 16 | public void handle(SelectionKey key) throws IOException { 17 | ServerSocketChannel ssc = (ServerSocketChannel) key.channel(); 18 | SocketChannel sc = ssc.accept(); // never null, nonblocking 19 | System.out.println("Someone connected: " + sc); 20 | sc.configureBlocking(false); 21 | pendingData.put(sc, new ConcurrentLinkedQueue<>()); 22 | 23 | sc.register(key.selector(), SelectionKey.OP_READ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/handler/ReadHandler.java: -------------------------------------------------------------------------------- 1 | package handler; 2 | 3 | import handler.*; 4 | import util.*; 5 | 6 | import java.io.*; 7 | import java.nio.*; 8 | import java.nio.channels.*; 9 | import java.util.*; 10 | 11 | public class ReadHandler implements Handler { 12 | private final Map> pendingData; 13 | 14 | public ReadHandler(Map> pendingData) { 15 | this.pendingData = pendingData; 16 | } 17 | 18 | public void handle(SelectionKey key) throws IOException { 19 | SocketChannel sc = (SocketChannel) key.channel(); 20 | ByteBuffer buf = ByteBuffer.allocateDirect(80); 21 | int read = sc.read(buf); 22 | if (read == -1) { 23 | pendingData.remove(sc); 24 | return; 25 | } 26 | if (read > 0) { 27 | Util.transmogrify(buf); 28 | pendingData.get(sc).add(buf); 29 | key.interestOps(SelectionKey.OP_WRITE); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/server/BlockingNIOServer.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import handler.*; 4 | 5 | import java.io.*; 6 | import java.net.*; 7 | import java.nio.channels.*; 8 | import java.util.concurrent.*; 9 | 10 | public class BlockingNIOServer { 11 | public static void main(String... args) throws IOException { 12 | ServerSocketChannel ssc = ServerSocketChannel.open(); 13 | ssc.bind(new InetSocketAddress(8080)); 14 | 15 | ExecutorService pool = new ThreadPoolExecutor( 16 | 10, 100, 17 | 0L, TimeUnit.MILLISECONDS, 18 | new LinkedBlockingQueue(1000)); 19 | Handler handler = 20 | new ExecutorServiceHandler<>( 21 | pool, 22 | new PrintingHandler<>( 23 | new BlockingChannelHandler( 24 | new TransmogrifyChannelHandler()))); 25 | while (true) { 26 | SocketChannel sc = ssc.accept(); // never null - blocks 27 | handler.handle(sc); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/handler/WriteHandler.java: -------------------------------------------------------------------------------- 1 | package handler; 2 | 3 | import handler.*; 4 | 5 | import java.io.*; 6 | import java.nio.*; 7 | import java.nio.channels.*; 8 | import java.util.*; 9 | 10 | public class WriteHandler implements Handler { 11 | private final Map> pendingData; 12 | 13 | public WriteHandler(Map> pendingData) { 14 | this.pendingData = pendingData; 15 | } 16 | 17 | public void handle(SelectionKey key) throws IOException { 18 | SocketChannel sc = (SocketChannel) key.channel(); 19 | Queue queue = pendingData.get(sc); 20 | while(!queue.isEmpty()) { 21 | ByteBuffer buf = queue.peek(); 22 | int written = sc.write(buf); 23 | if (written == -1) { 24 | sc.close(); 25 | pendingData.remove(sc); 26 | return; 27 | } 28 | if (buf.hasRemaining()) { 29 | return; 30 | } else { 31 | queue.remove(); 32 | } 33 | } 34 | key.interestOps(SelectionKey.OP_READ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/server/SingleThreadedPollingNonBlockingServer.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import handler.*; 4 | 5 | import java.io.*; 6 | import java.net.*; 7 | import java.nio.channels.*; 8 | import java.util.*; 9 | 10 | public class SingleThreadedPollingNonBlockingServer { 11 | public static void main(String... args) throws IOException { 12 | ServerSocketChannel ssc = ServerSocketChannel.open(); 13 | ssc.bind(new InetSocketAddress(8080)); 14 | ssc.configureBlocking(false); 15 | 16 | Handler handler = 17 | new ExceptionHandler<>( 18 | new TransmogrifyChannelHandler()); 19 | 20 | Collection sockets = new ArrayList<>(); 21 | while (true) { 22 | SocketChannel newSocket = ssc.accept(); // mostly null - never blocks 23 | if (newSocket != null) { 24 | sockets.add(newSocket); 25 | System.out.println("Connected to " + newSocket); 26 | newSocket.configureBlocking(false); 27 | } 28 | 29 | for (Iterator it = sockets.iterator(); it.hasNext(); ) { 30 | SocketChannel sc = it.next(); 31 | if (sc.isConnected()) { 32 | handler.handle(sc); 33 | } else { 34 | it.remove(); 35 | } 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/handler/PooledReadHandler.java: -------------------------------------------------------------------------------- 1 | package handler; 2 | 3 | import util.*; 4 | 5 | import java.io.*; 6 | import java.nio.*; 7 | import java.nio.channels.*; 8 | import java.util.*; 9 | import java.util.concurrent.*; 10 | 11 | public class PooledReadHandler implements Handler { 12 | private final ExecutorService pool; 13 | private final Map> pendingData; 14 | private final Queue selectorActions; 15 | 16 | public PooledReadHandler(ExecutorService pool, 17 | Map> pendingData, 18 | Queue selectorActions) { 19 | this.pool = pool; 20 | this.pendingData = pendingData; 21 | this.selectorActions = selectorActions; 22 | } 23 | 24 | public void handle(SelectionKey key) throws IOException { 25 | SocketChannel sc = (SocketChannel) key.channel(); 26 | ByteBuffer buf = ByteBuffer.allocateDirect(80); 27 | int read = sc.read(buf); 28 | if (read == -1) { 29 | pendingData.remove(sc); 30 | return; 31 | } 32 | if (read > 0) { 33 | pool.submit(() -> { 34 | Util.transmogrify(buf); 35 | pendingData.get(sc).add(buf); 36 | selectorActions.add(() -> key.interestOps(SelectionKey.OP_WRITE)); 37 | key.selector().wakeup(); 38 | }); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/server/SingleThreadedSelectorNonBlockingServer.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import handler.*; 4 | 5 | import java.io.*; 6 | import java.net.*; 7 | import java.nio.*; 8 | import java.nio.channels.*; 9 | import java.util.*; 10 | 11 | public class SingleThreadedSelectorNonBlockingServer { 12 | public static void main(String... args) throws IOException { 13 | ServerSocketChannel ssc = ServerSocketChannel.open(); 14 | ssc.bind(new InetSocketAddress(8080)); 15 | ssc.configureBlocking(false); 16 | Selector selector = Selector.open(); 17 | ssc.register(selector, SelectionKey.OP_ACCEPT); 18 | 19 | Map> pendingData = new HashMap<>(); 20 | Handler acceptHandler = new AcceptHandler(pendingData); 21 | Handler readHandler = new ReadHandler(pendingData); 22 | Handler writeHandler = new WriteHandler(pendingData); 23 | 24 | while (true) { 25 | selector.select(); 26 | Set keys = selector.selectedKeys(); 27 | for (Iterator it = keys.iterator(); it.hasNext(); ) { 28 | SelectionKey key = it.next(); 29 | it.remove(); 30 | if (key.isValid()) { 31 | if (key.isAcceptable()) { 32 | acceptHandler.handle(key); 33 | } else if (key.isReadable()) { 34 | readHandler.handle(key); 35 | } else if (key.isWritable()) { 36 | writeHandler.handle(key); 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/server/SelectorNonBlockingServerWithWorkerPool.java: -------------------------------------------------------------------------------- 1 | package server; 2 | 3 | import handler.*; 4 | 5 | import java.io.*; 6 | import java.net.*; 7 | import java.nio.*; 8 | import java.nio.channels.*; 9 | import java.util.*; 10 | import java.util.concurrent.*; 11 | 12 | public class SelectorNonBlockingServerWithWorkerPool { 13 | public static void main(String... args) throws IOException { 14 | ServerSocketChannel ssc = ServerSocketChannel.open(); 15 | ssc.bind(new InetSocketAddress(8080)); 16 | ssc.configureBlocking(false); 17 | Selector selector = Selector.open(); 18 | ssc.register(selector, SelectionKey.OP_ACCEPT); 19 | 20 | ExecutorService pool = Executors.newFixedThreadPool(10); 21 | Queue selectorActions = new ConcurrentLinkedQueue<>(); 22 | 23 | Map> pendingData = new ConcurrentHashMap<>(); 24 | Handler acceptHandler = new AcceptHandler(pendingData); 25 | Handler readHandler = new PooledReadHandler(pool, pendingData, selectorActions); 26 | Handler writeHandler = new WriteHandler(pendingData); 27 | 28 | while (true) { 29 | selector.select(); 30 | processSelectorActions(selectorActions); 31 | Set keys = selector.selectedKeys(); 32 | for (Iterator it = keys.iterator(); it.hasNext(); ) { 33 | SelectionKey key = it.next(); 34 | it.remove(); 35 | if (key.isValid()) { 36 | if (key.isAcceptable()) { 37 | acceptHandler.handle(key); 38 | } else if (key.isReadable()) { 39 | readHandler.handle(key); 40 | } else if (key.isWritable()) { 41 | writeHandler.handle(key); 42 | } 43 | } 44 | } 45 | } 46 | } 47 | 48 | private static void processSelectorActions(Queue selectorActions) { 49 | Runnable action; 50 | while((action = selectorActions.poll()) != null) { 51 | action.run(); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /Transmogrifier.iws: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 193 | 194 | 195 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 233 | 234 | 235 | 236 | 239 | 240 | 243 | 244 | 245 | 246 | 249 | 250 | 253 | 254 | 257 | 258 | 259 | 260 | 263 | 264 | 267 | 268 | 271 | 272 | 275 | 276 | 277 | 278 | 281 | 282 | 285 | 286 | 289 | 290 | 293 | 294 | 295 | 296 | 299 | 300 | 303 | 304 | 307 | 308 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 385 | 386 | 387 | 388 | 391 | 392 | 407 | 408 | 409 | 410 | 413 | 414 | 429 | 430 | 431 | 432 | 435 | 436 | 451 | 452 | 453 | 454 | 457 | 458 | 473 | 474 | 475 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 497 | 498 | 499 | 500 | 501 | 502 | 513 | 514 | 515 | 516 | 534 | 541 | 542 | 543 | 544 | 558 | 559 | 560 | 561 | 562 | 563 | 584 | 597 | 598 | 599 | 618 | 619 | 628 | 632 | 633 | 634 | 651 | 652 | 653 | 666 | 667 | 668 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | localhost 704 | 5050 705 | 706 | 707 | 708 | 709 | 710 | 711 | 1399023567720 712 | 1399023567720 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 789 | 792 | 793 | 794 | 796 | 797 | 800 | 801 | 802 | 803 | 804 | 805 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 | 892 | 893 | 894 | 895 | 896 | 897 | 898 | 899 | 900 | 901 | 902 | 903 | 904 | 905 | 906 | 907 | 908 | 909 | 910 | 911 | 912 | 913 | 914 | 915 | 916 | 917 | 918 | 919 | 920 | 921 | 922 | 923 | 924 | 925 | 926 | 927 | 928 | 929 | 930 | 931 | 932 | 933 | 934 | 935 | 936 | 937 | 938 | 939 | 940 | 941 | 942 | 943 | 944 | 945 | 946 | 947 | 948 | 949 | 950 | 951 | 952 | 953 | 954 | 955 | 956 | 957 | 958 | 959 | 960 | 961 | 962 | 963 | 964 | 965 | 966 | 967 | 968 | 969 | 970 | 971 | 972 | 973 | 974 | 975 | 976 | 977 | 978 | 979 | 980 | 981 | 982 | 983 | 984 | 985 | 986 | 987 | 988 | 989 | 990 | 991 | 992 | 993 | 994 | 995 | 996 | 997 | 998 | 999 | 1000 | 1001 | 1002 | 1003 | 1004 | 1005 | 1006 | 1007 | 1008 | 1009 | 1010 | 1011 | 1012 | 1013 | 1014 | 1015 | 1016 | 1017 | 1018 | 1019 | 1020 | 1021 | 1022 | 1023 | 1024 | 1025 | 1026 | 1027 | 1028 | 1029 | 1030 | 1031 | 1032 | 1033 | 1034 | 1035 | 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 1042 | 1043 | 1044 | 1045 | 1046 | 1047 | 1048 | 1049 | 1050 | 1051 | 1052 | 1053 | 1054 | 1055 | 1056 | 1057 | 1058 | 1059 | 1060 | 1061 | 1062 | 1063 | 1064 | 1065 | 1066 | 1067 | 1068 | 1069 | 1070 | 1071 | 1072 | 1073 | 1074 | 1075 | 1076 | 1077 | 1078 | 1079 | 1080 | 1081 | 1082 | 1083 | 1084 | 1085 | 1086 | 1087 | 1088 | 1089 | 1090 | 1091 | 1092 | 1093 | 1094 | 1095 | 1096 | 1097 | 1098 | 1099 | 1100 | 1101 | 1102 | 1103 | 1104 | 1105 | 1106 | 1107 | 1108 | 1109 | 1110 | 1111 | 1112 | 1113 | 1114 | 1115 | 1116 | 1117 | 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1129 | 1130 | 1131 | 1132 | 1133 | 1134 | No facets are configured 1135 | 1136 | 1141 | 1142 | 1143 | 1144 | 1145 | 1146 | 1147 | 1152 | 1153 | 1154 | 1155 | 1156 | 1157 | 1.6 1158 | 1159 | 1164 | 1165 | 1166 | 1167 | 1168 | 1169 | Transmogrifier 1170 | 1171 | 1177 | 1178 | 1179 | 1180 | 1181 | 1182 | 1.7 1183 | 1184 | 1189 | 1190 | 1191 | 1192 | 1193 | 1194 | 1195 | 1200 | 1201 | 1202 | 1203 | 1204 | 1205 | 1206 | 1207 | -------------------------------------------------------------------------------- /Transmogrifier.ipr: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | 24 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 1031 | 1032 | 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 1042 | 1043 | 1044 | 1045 | 1046 | 1047 | 1048 | 1049 | 1050 | 1051 | 1052 | 1053 | 1054 | 1055 | 1056 | 1057 | 1058 | 1059 | 1060 | 1061 | 1062 | 1063 | 1064 | 1065 | 1066 | 1067 | 1068 | 1069 | 1070 | 1071 | 1072 | 1073 | 1074 | 1075 | 1076 | 1077 | 1078 | 1079 | 1080 | 1081 | 1082 | 1083 | 1084 | 1085 | 1086 | 1087 | 1088 | 1089 | 1090 | 1091 | 1092 | 1093 | 1094 | 1095 | 1096 | 1097 | 1098 | 1099 | 1100 | 1101 | 1102 | 1103 | 1104 | 1105 | 1106 | 1107 | 1108 | 1109 | 1110 | 1111 | 1112 | 1113 | 1114 | 1115 | 1116 | 1117 | 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | 1126 | 1127 | 1128 | 1129 | 1130 | 1131 | 1132 | 1133 | 1134 | 1135 | 1136 | 1137 | 1138 | 1139 | 1140 | 1141 | 1142 | 1143 | 1144 | 1145 | 1146 | 1147 | 1148 | 1149 | 1150 | 1151 | 1152 | 1153 | 1154 | 1155 | 1156 | 1157 | 1158 | 1159 | 1160 | 1161 | 1162 | 1163 | 1164 | 1165 | 1166 | 1167 | 1168 | 1169 | 1170 | --------------------------------------------------------------------------------