| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="utf-8"> |
| <meta name="viewport" content="width=device-width,initial-scale=1"> |
| <title>Apache Freemarker :: PLC4X</title> |
| <meta name="generator" content="Antora 3.1.14"> |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| https://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| --> |
| <link rel="stylesheet" href="/_/css/site.css"> |
| <link rel="stylesheet" href="/_/css/header.css"> |
| <link rel="stylesheet" href="/_/css/vars.css"> |
| <link rel="stylesheet" href="/_/css/all.min.css" type="text/css"/> |
| <script src="https://www.apachecon.com/event-images/snippet.js" type="text/javascript"></script> |
| <link rel="icon" type="image/x-icon" href="/images/favicon.ico"> </head> |
| <body class="article"> |
| <header class="header"> |
| <nav class="navbar"> |
| <div class="navbar-brand"> |
| <a class="navbar-item" href="../../../../.."> |
| <img src="../../../../../plc4x/pre-release/_images/apache-plc4x-oakleaf-dark-small.png" alt="Apache PLC4X"> |
| </a> |
| <div class="navbar-item search hide-for-print"> |
| <div id="search-field" class="field"> |
| <input id="search-input" type="text" placeholder="Search the docs"> |
| </div> |
| </div> |
| <button class="navbar-burger" aria-controls="topbar-nav" aria-expanded="false" aria-label="Toggle main menu"> |
| <span></span> |
| <span></span> |
| <span></span> |
| </button> |
| </div> |
| <div id="topbar-nav" class="navbar-menu"> |
| <div class="navbar-end justify-content-center"> |
| <a class="navbar-item" href="../../../../../">Home</a> |
| <a class="navbar-item" href="../../../../../plc4x/pre-release/users">Users</a> |
| <a class="navbar-item" href="../../../../../plc4x/pre-release/developers">Developers</a> |
| <div class="navbar-item has-dropdown is-hoverable"> |
| <a class="navbar-link" href="https://www.apache.org">Apache</a> |
| <div class="navbar-dropdown"> |
| <a class="navbar-item" href="https://www.apache.org">Apache Homepage</a> |
| <a class="navbar-item" href="https://www.apache.org/licenses/">License</a> |
| <a class="navbar-item" href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a> |
| <a class="navbar-item" href="https://www.apache.org/foundation/thanks.html">Thanks</a> |
| <a class="navbar-item" href="https://www.apache.org/security/">Security</a> |
| <a class="navbar-item" href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy</a> |
| <a class="navbar-item" href="https://www.apache.org/foundation/policies/conduct">Code of Conduct</a> |
| <a class="navbar-item" href="https://events.apache.org/">Upcoming Events</a> |
| </div> |
| </div> |
| <div class="navbar-item"> |
| <span class="control"> |
| <a class="fa-brands fa-github" href="https://github.com/apache/plc4x"></a> |
| </span> |
| </div> |
| <div class="navbar-item"> |
| <span class="control"> |
| <a class="button is-primary" href="../../../../../plc4x/pre-release/users/download.html">Download</a> |
| </span> |
| </div> |
| <a class="acevent" data-format="wide"></a> |
| </div> |
| </div> |
| </nav> |
| </header> |
| <div class="body"> |
| <div class="nav-container" data-component="plc4x" data-version="pre-release"> |
| <aside class="nav"> |
| <div class="panels"> |
| <div class="nav-panel-menu is-active" data-panel="menu"> |
| <nav class="nav-menu"> |
| <button class="nav-menu-toggle" aria-label="Toggle expand/collapse all" style="display: none"></button> |
| <h3 class="title"><a href="../../../users/index.html">PLC4X</a></h3> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="0"> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="1"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../../users/index.html">Users</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../users/download.html">Download</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../users/adopters.html">Adopters</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../users/issues.html">Bug & Issue Tracker</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../users/commercial-support.html">Commercial Support</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../../users/getting-started/index.html">Getting Started</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/getting-started/plc4c.html">Getting Started with C</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/getting-started/plc4cs.html">Getting Started with C#</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/getting-started/plc4go.html">Getting Started with Go</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/getting-started/plc4j.html">Getting Started with Java</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/getting-started/plc4py.html">Getting Started with Python</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/getting-started/using-snapshots.html">Using SNAPSHOT versions</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/getting-started/general-concepts.html">General Concepts</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/getting-started/virtual-modbus.html">Virtual Modbus</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/getting-started/opcua-client-certificate.html">OPC UA : Client certificate creation</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../users/blogs-videos-and-slides.html">Blogs, Videos and Slides on Apache PLC4X</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../../users/protocols/index.html">Protocols</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/ab-eth.html">AB-ETH</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/ads.html">ADS (Automation Device Specification)</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/bacnet.html">BACnet/IP</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/c-bus.html">C-Bus</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/canopen.html">CANopen</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/ctrlx.html">CtlrX</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/deltav.html">DeltaV</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/df1.html">DF1</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/eip.html">EtherNet/IP</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/firmata.html">Firmata</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/genericcan.html">Generic CAN</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/iec-60870.html">IEC-60870</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/knxnetip.html">KNXnet/IP</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/logix.html">Logix</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/modbus.html">Modbus (TCP/UDP/Serial)</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/opcua.html">OPC UA</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/open-protocol.html">Open-Protocol (Torque-Tools)</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/plc4x.html">PLC4X (Proxy) (TCP)</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/profinet.html">Profinet (In Development)</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/s7.html">S7 (Step7)</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/s7-light.html">S7-Light (Step7)</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/simulated.html">Simulated</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/protocols/umas.html">UMAS (Schneider Electric PLCs)</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../../users/transports/index.html">Transports</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/transports/tcp.html">TCP</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/transports/udp.html">UDP</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/transports/serial.html">Serial Port</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/transports/socketcan.html">SocketCAN</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/transports/raw-socket.html">Raw Socket</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/transports/pcap-replay.html">PCAP Replay</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../../users/integrations/index.html">Integrations</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/integrations/apache-calcite.html">Apache Calcite</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/integrations/apache-camel.html">Apache Camel</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/integrations/apache-iotdb.html">Apache IotDB</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/integrations/apache-kafka.html">Apache Kafka</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/integrations/apache-nifi.html">Apache NiFi</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/integrations/apache-streampipes.html">Apache StreamPipes</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/integrations/eclipse-ditto.html">Eclipse Ditto</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/integrations/eclipse-milo.html">Eclipse Milo (OPC UA Server)</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../../users/tools/index.html">Tools</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/tools/capture-replay.html">Capture Replay</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/tools/connection-cache.html">The Connection Cache concept</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/tools/opm.html">Object PLC Mapping</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/tools/scraper.html">Scraper</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../../users/tools/testing.html">Testing (or using PLC4X without a PLC)</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../users/industry40.html">Industry 4.0 with Apache</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../../users/security.html">Security Vulnerabilities</a> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="0"> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="1"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../index.html">Developers</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="2"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../preparing/index.html">Preparing your Computer</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../preparing/linux.html">Linux</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../preparing/macos.html">Mac OS</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../preparing/windows.html">Windows</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../building.html">Building PLC4X</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../contributing.html">Contributing</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../tutorials/index.html">Tutorials</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../tutorials/writing-driver.html">Strategy for creating a new Driver</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../tutorials/testing-serializers-and-parsers.html">Testing Serializers and Parsers</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../index.html">Code Generation</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../protocol/mspec.html">The MSpec format</a> |
| </li> |
| <li class="nav-item is-current-page" data-depth="3"> |
| <a class="nav-link" href="freemarker.html">Apache Freemarker</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../protocol/df1.html">Example: DF1 MSpec</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../protocols/index.html">Usage of protocols</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../protocols/ads/protocol.html">Beckhoff ADS Protocol</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../protocols/eip/protocol.html">EIP Protocol</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../infrastructure/index.html">Infrastructure</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../infrastructure/ci.html">Continuous Integration</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../infrastructure/issues.html">Bug & Issue Tracker</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../infrastructure/sonar.html">Code Analysis</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../infrastructure/wiki.html">WIKI</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../infrastructure/vm.html">The PLC4X Project VM</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../infrastructure/website.html">Generating the Website</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <button class="nav-item-toggle"></button> |
| <a class="nav-link" href="../../release/index.html">Releasing and Validating Releases</a> |
| <ul class="nav-list"> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../release/release.html">Releasing PLC4X</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../release/extras.html">Releasing PLC4X-Extras</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../release/validation.html">Validating a staged release</a> |
| </li> |
| <li class="nav-item" data-depth="3"> |
| <a class="nav-link" href="../../release/build-tools.html">Releasing PLC4X Build-Tools</a> |
| </li> |
| </ul> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../testing/index.html">Setup for testing</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../tools.html">Tools</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../team.html">Team</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../decisions.html">Decision Making</a> |
| </li> |
| <li class="nav-item" data-depth="2"> |
| <a class="nav-link" href="../../maturity.html">Apache Maturity Model Assessment for PLC4X</a> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </nav> |
| </div> |
| <div class="nav-panel-explore" data-panel="explore"> |
| <div class="context"> |
| <span class="title">PLC4X</span> |
| <span class="version">pre-release</span> |
| </div> |
| <ul class="components"> |
| <li class="component is-current"> |
| <div class="title"><a href="../../../../latest/users/index.html">PLC4X</a></div> |
| <ul class="versions"> |
| <li class="version is-current"> |
| <a href="../../../users/index.html">pre-release</a> |
| </li> |
| <li class="version is-latest"> |
| <a href="../../../../latest/users/index.html">latest</a> |
| </li> |
| <li class="version"> |
| <a href="../../../../0.12.0/users/index.html">0.12.0</a> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| </div> |
| </div> |
| </aside> |
| </div> |
| <main class="article"> |
| <div class="toolbar" role="navigation"> |
| <button class="nav-toggle"></button> |
| <nav class="breadcrumbs" aria-label="breadcrumbs"> |
| <ul> |
| <li><a href="../../../users/index.html">PLC4X</a></li> |
| <li><a href="../../index.html">Developers</a></li> |
| <li><a href="../index.html">Code Generation</a></li> |
| <li><a href="freemarker.html">Apache Freemarker</a></li> |
| </ul> |
| </nav> |
| <div class="page-versions"> |
| <button class="version-menu-toggle" title="Show other versions of page">pre-release</button> |
| <div class="version-menu"> |
| <a class="version is-current" href="freemarker.html">pre-release</a> |
| <a class="version" href="../../../../latest/developers/code-gen/language/freemarker.html">latest</a> |
| <a class="version" href="../../../../0.12.0/developers/code-gen/language/freemarker.html">0.12.0</a> |
| </div> |
| </div> |
| <div class="edit-this-page"><a href="https://github.com/apache/plc4x/edit/develop/website/asciidoc/modules/developers/pages/code-gen/language/freemarker.adoc">Edit this Page</a></div> |
| </div> |
| <div class="content"> |
| <aside class="toc sidebar" data-title="Contents" data-levels="2"> |
| <div class="toc-menu"></div> |
| </aside> |
| <article class="doc"> |
| <h1 class="page">Apache Freemarker</h1> |
| <div id="preamble"> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>For the Freemarker language output we are using an unmodified version of <a href="https://freemarker.apache.org">Apache Freemarker</a> to generate output.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The boilerplate code for providing a PLC4X language module is located in the <code>org.apache.plc4x.plugins:plc4x-code-generation-language-base-freemarker</code> maven module, inside the <code>FreemarkerLanguageOutput</code> class.</p> |
| </div> |
| <div class="paragraph"> |
| <p>This class configures a Freemarker context and provides standardized attributes inside this:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>packageName: Java style package name which can be used to create some form of directory structure.</p> |
| </li> |
| <li> |
| <p>typeName: Simple string type name</p> |
| </li> |
| <li> |
| <p>type: <code>ComplexTypeDefinition</code> instance containing all the information for the type that code should be generated for.</p> |
| </li> |
| <li> |
| <p>helper: As some times it is pretty complicated to create all the output in Freemarker, the helper allows to provide code that is used by the template that help with generating output.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>A Freemarker-based output module, has to provide a set of <code>Template</code> instances as well as provide a <code>FreemarkerLanguageTemplateHelper</code> instance.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In general, we distinguish between these types of templates:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><code>Spec Templates</code> (Global output generated once per driver in total)</p> |
| </li> |
| <li> |
| <p><code>Complex Type Templates</code> (Generates output for a complex type)</p> |
| </li> |
| <li> |
| <p><code>Enum Templates</code> (Generates output for enum types)</p> |
| </li> |
| <li> |
| <p><code>DataIO Templates</code> (Generates output for reading and writing PlcValues, which are our PLC4X form of presenting input and output data to our users)</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>For each of these, the developer can provide a list of templates, which then can generate multiple files per type (Which is important for languages such as <code>C</code> where for every type we need to generate a <code>Header file (.h)</code> and an <code>Implementation (.c)</code>)</p> |
| </div> |
| <div class="paragraph"> |
| <p>What the <code>FreemarkerLanguageOutput</code> then does, is iterate over all types provided by the protocol module, and then iterate over all templates the current language defines.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The only convention used in this utility, is that the first line of output a template generates will be treated as the path relative to the base output directory.</p> |
| </div> |
| <div class="paragraph"> |
| <p>It will automatically create all needed intermediate directories and generate the rest of the input to the file specified by the first line.</p> |
| </div> |
| <div class="paragraph"> |
| <p>If this line is empty, the output is skipped for this type.</p> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="_example_java_output"><a class="anchor" href="#_example_java_output"></a>Example <code>Java</code> output</h2> |
| <div class="sectionbody"> |
| <div class="literalblock"> |
| <div class="content"> |
| <pre>package org.apache.plc4x.language.java; |
| |
| import com.google.googlejavaformat.java.Formatter; |
| import com.google.googlejavaformat.java.FormatterException; |
| import freemarker.template.Configuration; |
| import freemarker.template.Template; |
| import org.apache.commons.io.FileUtils; |
| import org.apache.plc4x.plugins.codegenerator.protocol.freemarker.FreemarkerLanguageOutput; |
| import org.apache.plc4x.plugins.codegenerator.protocol.freemarker.FreemarkerLanguageTemplateHelper; |
| import org.apache.plc4x.plugins.codegenerator.types.definitions.TypeDefinition; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.nio.charset.StandardCharsets; |
| import java.util.*; |
| |
| public class JavaLanguageOutput extends FreemarkerLanguageOutput { |
| |
| private static final Logger LOGGER = LoggerFactory.getLogger(JavaLanguageOutput.class); |
| |
| private final Formatter formatter = new Formatter(); |
| |
| @Override |
| public String getName() { |
| return "Java"; |
| } |
| |
| @Override |
| public Set<String> supportedOptions() { |
| return Collections.singleton("package"); |
| } |
| |
| @Override |
| public List<String> supportedOutputFlavors() { |
| return Arrays.asList("read-write", "read-only", "passive"); |
| } |
| |
| @Override |
| protected List<Template> getSpecTemplates(Configuration freemarkerConfiguration) { |
| return Collections.emptyList(); |
| } |
| |
| @Override |
| protected List<Template> getComplexTypeTemplates(Configuration freemarkerConfiguration) throws IOException { |
| return Arrays.asList( |
| freemarkerConfiguration.getTemplate("templates/java/pojo-template.java.ftlh"), |
| freemarkerConfiguration.getTemplate("templates/java/io-template.java.ftlh")); |
| } |
| |
| @Override |
| protected List<Template> getEnumTypeTemplates(Configuration freemarkerConfiguration) throws IOException { |
| return Collections.singletonList( |
| freemarkerConfiguration.getTemplate("templates/java/enum-template.java.ftlh")); |
| } |
| |
| @Override |
| protected List<Template> getDataIoTemplates(Configuration freemarkerConfiguration) throws IOException { |
| return Collections.singletonList( |
| freemarkerConfiguration.getTemplate("templates/java/data-io-template.java.ftlh")); |
| } |
| |
| @Override |
| protected FreemarkerLanguageTemplateHelper getHelper(TypeDefinition thisType, String protocolName, String flavorName, Map<String, TypeDefinition> types, |
| Map<String, String> options) { |
| return new JavaLanguageTemplateHelper(thisType, protocolName, flavorName, types, options); |
| } |
| |
| @Override |
| protected void postProcessTemplateOutput(File outputFile) { |
| try { |
| FileUtils.writeStringToFile( |
| outputFile, |
| formatter.formatSourceAndFixImports( |
| FileUtils.readFileToString(outputFile, StandardCharsets.UTF_8) |
| ), |
| StandardCharsets.UTF_8 |
| ); |
| } catch (IOException | FormatterException e) { |
| LOGGER.error("Error formatting {}", outputFile, e); |
| } |
| } |
| }</pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The <code>getName</code> method returns <code>Java</code>, this is what needs to be defined in the <code>plc4x-maven-plugin</code> configuration in the <code>language</code> option in order to select this output format.</p> |
| </div> |
| <div class="paragraph"> |
| <p><code>supportedOptions</code> tells the plugin which <code>option</code> tags this code-generation output supports. In case of the <code>Java</code> output, this is only the <code>package</code> option, which defines the package name of the generated output.</p> |
| </div> |
| <div class="paragraph"> |
| <p>With <code>supportedOutputFlavors</code> we tell the user, that in general we support the three options: <code>read-write</code>, <code>read-only</code> and <code>passive</code> as valid inputs for the <code>outputFlavor</code> config option of the code-generation plugin.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In this case Java doesn’t require any global files being generated for java, so we simply return an empty collection.</p> |
| </div> |
| <div class="paragraph"> |
| <p>For complex types, we currently use two templates (however this will soon be reduced to one). So for every complex type in a protocol definition, the templates: <code>templates/java/pojo-template.java.ftlh</code> and <code>templates/java/io-template.java.ftlh</code> will be executed.</p> |
| </div> |
| <div class="paragraph"> |
| <p>In case of enum types, only one template is being used.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Same as for data-io.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The next important method is the <code>getHelper</code> method, which returns an object, that is passed to the templates with the name <code>helper</code>. As mentioned before, a lot of operations would be too complex to implement in pure Freemarker code, so with these helpers every language can provide a helper utility for handling the complex operations.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Here an example for a part of a template for generating Java POJOs:</p> |
| </div> |
| <div class="literalblock"> |
| <div class="content"> |
| <pre>${helper.packageName(protocolName, languageName, outputFlavor)?replace(".", "/")}/${type.name}.java |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * https://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package ${helper.packageName(protocolName, languageName, outputFlavor)}; |
| |
| ... imports ... |
| |
| // Code generated by code-generation. DO NOT EDIT. |
| |
| public<#if type.isDiscriminatedParentTypeDefinition()> abstract</#if> class ${type.name}<#if type.parentType??> extends ${type.parentType.name}</#if> implements Message { |
| |
| ... SNIP ... |
| |
| }</pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>So as you can see, the first line will generate the file-path of the to be generated output.</p> |
| </div> |
| <div class="paragraph"> |
| <p>As when creating more and more outputs for different languages, we have realized, that a lot of the code needed in the <code>Helper</code> utility repeats, we therefore introduced a so-called <code>BaseFreemarkerLanguageTemplateHelper</code> which contains a lot of stuff, that is important when generating new language output.</p> |
| </div> |
| </div> |
| </div> |
| </article> |
| </div> |
| </main> |
| </div> |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| https://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| --> |
| <footer class="container-flex footer col-6" style="text-align:center;"> |
| <div class="col"></div> |
| <div class="col-6"> |
| Copyright © 2017-2026 <a href="https://www.apache.org/">The Apache Software Foundation.</a> All rights reserved.<br/> |
| Apache PLC4X, PLC4X, Apache, the Apache feather logo, and the Apache PLC4X project logo are either registered |
| trademarks or trademarks of The Apache Software Foundation in the United States and other countries. All other marks |
| mentioned may be trademarks or registered trademarks of their respective owners. |
| <br/> |
| </div> |
| <div>Home screen image taken from <a |
| href="https://flic.kr/p/chEftd">Flickr</a>, "Tesla Robot Dance" by Steve Jurvetson, licensed |
| under <a href="https://creativecommons.org/licenses/by/2.0/">CC BY 2.0 Generic</a>, image cropped |
| and blur effect added. |
| </div> |
| <div class="col"></div> |
| </footer> |
| <script id="site-script" src="../../../../../_/js/site.js" data-ui-root-path="../../../../../_"></script> |
| <script async src="../../../../../_/js/vendor/highlight.js"></script> |
| <script src="../../../../../_/js/vendor/lunr.js"></script> |
| <script src="../../../../../_/js/search-ui.js" id="search-ui-script" data-site-root-path="../../../../.." data-snippet-length="100" data-stylesheet="../../../../../_/css/search.css"></script> |
| <script async src="../../../../../search-index.js"></script> |
| </body> |
| </html> |