{#
   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

       http://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.
#}

class {{ class_name }}(ExternalTransform):
{% if description %}  """
  {{ description | wordwrap(78) | replace('\n', '\n  ') }}
  """{% endif %}
  identifier = "{{ identifier }}"

  def __init__(
      self,{% if parameters %}{% for param in parameters%}
      {{ param.name }}{% if 'default' in param %}={{ param.default }}{% endif %},{% endfor %}{% endif %}
      expansion_service=None):
    {% if parameters %}"""{% for param in parameters %}
    :param {{ param.name }}: ({{ param.type }}){% if param.description %}
      {{ param.description | wordwrap(72) | replace('\n', '\n      ') }} {% endif %}{% endfor %}
    """{% endif %}
    self.default_expansion_service = {{ default_expansion_service }}
    super().__init__(
        {% for param in parameters %}{{ param.name }}={{ param.name }},
        {% endfor %}expansion_service=expansion_service)
