/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.component.factory.infrastructure;
import info.ganglia.gmetric4j.gmetric.GMetric;
import info.ganglia.gmetric4j.gmetric.GMetric.UDPAddressingMode;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.management.MBeanServer;
import org.joda.beans.Bean;
import org.joda.beans.BeanBuilder;
import org.joda.beans.BeanDefinition;
import org.joda.beans.JodaBeanUtils;
import org.joda.beans.MetaProperty;
import org.joda.beans.Property;
import org.joda.beans.PropertyDefinition;
import org.joda.beans.impl.direct.DirectBeanBuilder;
import org.joda.beans.impl.direct.DirectMetaProperty;
import org.joda.beans.impl.direct.DirectMetaPropertyMap;
import org.slf4j.LoggerFactory;
import org.springframework.context.Lifecycle;
import com.codahale.metrics.JmxReporter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Slf4jReporter;
import com.codahale.metrics.ganglia.GangliaReporter;
import com.opengamma.component.ComponentRepository;
import com.opengamma.component.factory.AbstractComponentFactory;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.metric.OpenGammaMetricRegistry;
/**
* Component Factory to setup the metrics server.
* <p>
* This class is designed to allow protected methods to be overridden.
*/
@BeanDefinition
public class MetricsRepositoryComponentFactory extends AbstractComponentFactory {
/**
* The registry name.
*/
@PropertyDefinition(validate = "notEmpty")
private String _registryName;
/**
* Whether to publish over JMX.
*/
@PropertyDefinition
private boolean _jmxPublish = true;
/**
* Whether to publish over SLF4J.
*/
@PropertyDefinition
private boolean _slf4jPublish = true;
/**
* Whether to publish over Ganglia.
*/
@PropertyDefinition
private boolean _gangliaPublish;
/**
* The Ganglia address.
*/
@PropertyDefinition
private String _gangliaAddress;
/**
* The Ganglia port.
*/
@PropertyDefinition
private Integer _gangliaPort;
/**
* The Ganglia addressing mode.
*/
@PropertyDefinition
private String _gangliaAddressingMode;
/**
* The Ganglia time to live.
*/
@PropertyDefinition
private Integer _gangliaTtl = 1;
//-------------------------------------------------------------------------
@Override
public void init(ComponentRepository repo, LinkedHashMap<String, String> configuration) throws Exception {
MetricRegistry summaryRegistry = new MetricRegistry();
MetricRegistry detailedRegistry = new MetricRegistry();
if (isJmxPublish()) {
initJmxPublish(repo, summaryRegistry, detailedRegistry);
}
if (isSlf4jPublish()) {
initSlf4jPublish(repo, summaryRegistry, detailedRegistry);
}
if (isGangliaPublish()) {
initGangliaPublish(repo, summaryRegistry, detailedRegistry);
}
OpenGammaMetricRegistry.setSummaryRegistry(summaryRegistry);
OpenGammaMetricRegistry.setDetailedRegistry(detailedRegistry);
// Register the registries so that where possible we can avoid
// using the static singleton
repo.registerComponent(MetricRegistry.class, "summary", summaryRegistry);
repo.registerComponent(MetricRegistry.class, "detailed", detailedRegistry);
}
/**
* Initialize publishing by JMX.
*
* @param repo the component repository, not null
* @param summaryRegistry the summary metrics registry, not null
* @param detailedRegistry the detailed metrics registry, not null
*/
protected void initJmxPublish(ComponentRepository repo, MetricRegistry summaryRegistry, MetricRegistry detailedRegistry) {
repo.registerLifecycle(new JmxReporterLifecycle(repo, summaryRegistry, detailedRegistry));
}
/**
* Initialize publishing by SLF4J.
*
* @param repo the component repository, not null
* @param summaryRegistry the summary metrics registry, not null
* @param detailedRegistry the detailed metrics registry, not null
*/
protected void initSlf4jPublish(ComponentRepository repo, MetricRegistry summaryRegistry, MetricRegistry detailedRegistry) {
Slf4jReporter logReporter = Slf4jReporter.forRegistry(summaryRegistry)
.outputTo(LoggerFactory.getLogger(OpenGammaMetricRegistry.class))
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.build();
logReporter.start(1, TimeUnit.MINUTES);
logReporter = Slf4jReporter.forRegistry(detailedRegistry)
.outputTo(LoggerFactory.getLogger(OpenGammaMetricRegistry.class))
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.build();
logReporter.start(1, TimeUnit.MINUTES);
}
/**
* Initialize publishing by Ganglia.
* <p>
* Only the summary registry is published.
*
* @param repo the component repository, not null
* @param summaryRegistry the summary metrics registry, not null
* @param detailedRegistry the detailed metrics registry, not null
*/
protected void initGangliaPublish(ComponentRepository repo, MetricRegistry summaryRegistry, MetricRegistry detailedRegistry) throws IOException {
ArgumentChecker.notNull(getGangliaAddress(), "gangliaAddress");
ArgumentChecker.notNull(getGangliaPort(), "gangliaPort");
ArgumentChecker.notNull(getGangliaAddressingMode(), "gangliaAddressingMode");
ArgumentChecker.notNull(getGangliaTtl(), "gangliaTtl");
GMetric ganglia = new GMetric(getGangliaAddress(), getGangliaPort(), UDPAddressingMode.valueOf(getGangliaAddressingMode()), getGangliaTtl(), true);
GangliaReporter gangliaReporter = GangliaReporter.forRegistry(summaryRegistry)
.convertRatesTo(TimeUnit.SECONDS)
.convertDurationsTo(TimeUnit.MILLISECONDS)
.build(ganglia);
repo.registerLifecycle(new GangliaReporterLifecycle(gangliaReporter));
}
//-------------------------------------------------------------------------
/**
* Lifecycle for JMX reporter.
* This delays registering the reporter with the MBean server until necessary.
*/
static final class JmxReporterLifecycle implements Lifecycle {
private final ComponentRepository _repo;
private final MetricRegistry _summaryRegistry;
private final MetricRegistry _detailedRegistry;
private volatile JmxReporter _summaryReporter;
private volatile JmxReporter _detailedReporter;
JmxReporterLifecycle(ComponentRepository repo, MetricRegistry summaryRegistry, MetricRegistry detailedRegistry) {
_repo = repo;
_summaryRegistry = summaryRegistry;
_detailedRegistry = detailedRegistry;
}
@Override
public void start() {
MBeanServer mbeanServer = _repo.findInstance(MBeanServer.class);
if (mbeanServer != null) {
_summaryReporter = JmxReporter.forRegistry(_summaryRegistry).registerWith(mbeanServer).build();
_detailedReporter = JmxReporter.forRegistry(_detailedRegistry).registerWith(mbeanServer).build();
} else {
// fallback to default MBeanServer
_summaryReporter = JmxReporter.forRegistry(_summaryRegistry).build();
_detailedReporter = JmxReporter.forRegistry(_detailedRegistry).build();
}
_summaryReporter.start();
_detailedReporter.start();
}
@Override
public void stop() {
if (_summaryReporter != null) {
_summaryReporter.stop();
_summaryReporter = null;
}
if (_detailedReporter != null) {
_detailedReporter.stop();
_detailedReporter = null;
}
}
@Override
public boolean isRunning() {
return _summaryReporter != null || _detailedReporter != null;
}
}
/**
* Lifecycle for Ganglia reporter.
* This delays registering the reporter with Ganglia until necessary.
*/
static final class GangliaReporterLifecycle implements Lifecycle {
private volatile GangliaReporter _gangliaReporter;
public GangliaReporterLifecycle(GangliaReporter gangliaReporter) {
_gangliaReporter = gangliaReporter;
}
@Override
public void start() {
if (_gangliaReporter != null) {
_gangliaReporter.start(1, TimeUnit.MINUTES);
}
}
@Override
public void stop() {
if (_gangliaReporter != null) {
_gangliaReporter.stop();
_gangliaReporter = null;
}
}
@Override
public boolean isRunning() {
return (_gangliaReporter != null);
}
}
//------------------------- AUTOGENERATED START -------------------------
///CLOVER:OFF
/**
* The meta-bean for {@code MetricsRepositoryComponentFactory}.
* @return the meta-bean, not null
*/
public static MetricsRepositoryComponentFactory.Meta meta() {
return MetricsRepositoryComponentFactory.Meta.INSTANCE;
}
static {
JodaBeanUtils.registerMetaBean(MetricsRepositoryComponentFactory.Meta.INSTANCE);
}
@Override
public MetricsRepositoryComponentFactory.Meta metaBean() {
return MetricsRepositoryComponentFactory.Meta.INSTANCE;
}
//-----------------------------------------------------------------------
/**
* Gets the registry name.
* @return the value of the property, not empty
*/
public String getRegistryName() {
return _registryName;
}
/**
* Sets the registry name.
* @param registryName the new value of the property, not empty
*/
public void setRegistryName(String registryName) {
JodaBeanUtils.notEmpty(registryName, "registryName");
this._registryName = registryName;
}
/**
* Gets the the {@code registryName} property.
* @return the property, not null
*/
public final Property<String> registryName() {
return metaBean().registryName().createProperty(this);
}
//-----------------------------------------------------------------------
/**
* Gets whether to publish over JMX.
* @return the value of the property
*/
public boolean isJmxPublish() {
return _jmxPublish;
}
/**
* Sets whether to publish over JMX.
* @param jmxPublish the new value of the property
*/
public void setJmxPublish(boolean jmxPublish) {
this._jmxPublish = jmxPublish;
}
/**
* Gets the the {@code jmxPublish} property.
* @return the property, not null
*/
public final Property<Boolean> jmxPublish() {
return metaBean().jmxPublish().createProperty(this);
}
//-----------------------------------------------------------------------
/**
* Gets whether to publish over SLF4J.
* @return the value of the property
*/
public boolean isSlf4jPublish() {
return _slf4jPublish;
}
/**
* Sets whether to publish over SLF4J.
* @param slf4jPublish the new value of the property
*/
public void setSlf4jPublish(boolean slf4jPublish) {
this._slf4jPublish = slf4jPublish;
}
/**
* Gets the the {@code slf4jPublish} property.
* @return the property, not null
*/
public final Property<Boolean> slf4jPublish() {
return metaBean().slf4jPublish().createProperty(this);
}
//-----------------------------------------------------------------------
/**
* Gets whether to publish over Ganglia.
* @return the value of the property
*/
public boolean isGangliaPublish() {
return _gangliaPublish;
}
/**
* Sets whether to publish over Ganglia.
* @param gangliaPublish the new value of the property
*/
public void setGangliaPublish(boolean gangliaPublish) {
this._gangliaPublish = gangliaPublish;
}
/**
* Gets the the {@code gangliaPublish} property.
* @return the property, not null
*/
public final Property<Boolean> gangliaPublish() {
return metaBean().gangliaPublish().createProperty(this);
}
//-----------------------------------------------------------------------
/**
* Gets the Ganglia address.
* @return the value of the property
*/
public String getGangliaAddress() {
return _gangliaAddress;
}
/**
* Sets the Ganglia address.
* @param gangliaAddress the new value of the property
*/
public void setGangliaAddress(String gangliaAddress) {
this._gangliaAddress = gangliaAddress;
}
/**
* Gets the the {@code gangliaAddress} property.
* @return the property, not null
*/
public final Property<String> gangliaAddress() {
return metaBean().gangliaAddress().createProperty(this);
}
//-----------------------------------------------------------------------
/**
* Gets the Ganglia port.
* @return the value of the property
*/
public Integer getGangliaPort() {
return _gangliaPort;
}
/**
* Sets the Ganglia port.
* @param gangliaPort the new value of the property
*/
public void setGangliaPort(Integer gangliaPort) {
this._gangliaPort = gangliaPort;
}
/**
* Gets the the {@code gangliaPort} property.
* @return the property, not null
*/
public final Property<Integer> gangliaPort() {
return metaBean().gangliaPort().createProperty(this);
}
//-----------------------------------------------------------------------
/**
* Gets the Ganglia addressing mode.
* @return the value of the property
*/
public String getGangliaAddressingMode() {
return _gangliaAddressingMode;
}
/**
* Sets the Ganglia addressing mode.
* @param gangliaAddressingMode the new value of the property
*/
public void setGangliaAddressingMode(String gangliaAddressingMode) {
this._gangliaAddressingMode = gangliaAddressingMode;
}
/**
* Gets the the {@code gangliaAddressingMode} property.
* @return the property, not null
*/
public final Property<String> gangliaAddressingMode() {
return metaBean().gangliaAddressingMode().createProperty(this);
}
//-----------------------------------------------------------------------
/**
* Gets the Ganglia time to live.
* @return the value of the property
*/
public Integer getGangliaTtl() {
return _gangliaTtl;
}
/**
* Sets the Ganglia time to live.
* @param gangliaTtl the new value of the property
*/
public void setGangliaTtl(Integer gangliaTtl) {
this._gangliaTtl = gangliaTtl;
}
/**
* Gets the the {@code gangliaTtl} property.
* @return the property, not null
*/
public final Property<Integer> gangliaTtl() {
return metaBean().gangliaTtl().createProperty(this);
}
//-----------------------------------------------------------------------
@Override
public MetricsRepositoryComponentFactory clone() {
return JodaBeanUtils.cloneAlways(this);
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj != null && obj.getClass() == this.getClass()) {
MetricsRepositoryComponentFactory other = (MetricsRepositoryComponentFactory) obj;
return JodaBeanUtils.equal(getRegistryName(), other.getRegistryName()) &&
(isJmxPublish() == other.isJmxPublish()) &&
(isSlf4jPublish() == other.isSlf4jPublish()) &&
(isGangliaPublish() == other.isGangliaPublish()) &&
JodaBeanUtils.equal(getGangliaAddress(), other.getGangliaAddress()) &&
JodaBeanUtils.equal(getGangliaPort(), other.getGangliaPort()) &&
JodaBeanUtils.equal(getGangliaAddressingMode(), other.getGangliaAddressingMode()) &&
JodaBeanUtils.equal(getGangliaTtl(), other.getGangliaTtl()) &&
super.equals(obj);
}
return false;
}
@Override
public int hashCode() {
int hash = 7;
hash = hash * 31 + JodaBeanUtils.hashCode(getRegistryName());
hash = hash * 31 + JodaBeanUtils.hashCode(isJmxPublish());
hash = hash * 31 + JodaBeanUtils.hashCode(isSlf4jPublish());
hash = hash * 31 + JodaBeanUtils.hashCode(isGangliaPublish());
hash = hash * 31 + JodaBeanUtils.hashCode(getGangliaAddress());
hash = hash * 31 + JodaBeanUtils.hashCode(getGangliaPort());
hash = hash * 31 + JodaBeanUtils.hashCode(getGangliaAddressingMode());
hash = hash * 31 + JodaBeanUtils.hashCode(getGangliaTtl());
return hash ^ super.hashCode();
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder(288);
buf.append("MetricsRepositoryComponentFactory{");
int len = buf.length();
toString(buf);
if (buf.length() > len) {
buf.setLength(buf.length() - 2);
}
buf.append('}');
return buf.toString();
}
@Override
protected void toString(StringBuilder buf) {
super.toString(buf);
buf.append("registryName").append('=').append(JodaBeanUtils.toString(getRegistryName())).append(',').append(' ');
buf.append("jmxPublish").append('=').append(JodaBeanUtils.toString(isJmxPublish())).append(',').append(' ');
buf.append("slf4jPublish").append('=').append(JodaBeanUtils.toString(isSlf4jPublish())).append(',').append(' ');
buf.append("gangliaPublish").append('=').append(JodaBeanUtils.toString(isGangliaPublish())).append(',').append(' ');
buf.append("gangliaAddress").append('=').append(JodaBeanUtils.toString(getGangliaAddress())).append(',').append(' ');
buf.append("gangliaPort").append('=').append(JodaBeanUtils.toString(getGangliaPort())).append(',').append(' ');
buf.append("gangliaAddressingMode").append('=').append(JodaBeanUtils.toString(getGangliaAddressingMode())).append(',').append(' ');
buf.append("gangliaTtl").append('=').append(JodaBeanUtils.toString(getGangliaTtl())).append(',').append(' ');
}
//-----------------------------------------------------------------------
/**
* The meta-bean for {@code MetricsRepositoryComponentFactory}.
*/
public static class Meta extends AbstractComponentFactory.Meta {
/**
* The singleton instance of the meta-bean.
*/
static final Meta INSTANCE = new Meta();
/**
* The meta-property for the {@code registryName} property.
*/
private final MetaProperty<String> _registryName = DirectMetaProperty.ofReadWrite(
this, "registryName", MetricsRepositoryComponentFactory.class, String.class);
/**
* The meta-property for the {@code jmxPublish} property.
*/
private final MetaProperty<Boolean> _jmxPublish = DirectMetaProperty.ofReadWrite(
this, "jmxPublish", MetricsRepositoryComponentFactory.class, Boolean.TYPE);
/**
* The meta-property for the {@code slf4jPublish} property.
*/
private final MetaProperty<Boolean> _slf4jPublish = DirectMetaProperty.ofReadWrite(
this, "slf4jPublish", MetricsRepositoryComponentFactory.class, Boolean.TYPE);
/**
* The meta-property for the {@code gangliaPublish} property.
*/
private final MetaProperty<Boolean> _gangliaPublish = DirectMetaProperty.ofReadWrite(
this, "gangliaPublish", MetricsRepositoryComponentFactory.class, Boolean.TYPE);
/**
* The meta-property for the {@code gangliaAddress} property.
*/
private final MetaProperty<String> _gangliaAddress = DirectMetaProperty.ofReadWrite(
this, "gangliaAddress", MetricsRepositoryComponentFactory.class, String.class);
/**
* The meta-property for the {@code gangliaPort} property.
*/
private final MetaProperty<Integer> _gangliaPort = DirectMetaProperty.ofReadWrite(
this, "gangliaPort", MetricsRepositoryComponentFactory.class, Integer.class);
/**
* The meta-property for the {@code gangliaAddressingMode} property.
*/
private final MetaProperty<String> _gangliaAddressingMode = DirectMetaProperty.ofReadWrite(
this, "gangliaAddressingMode", MetricsRepositoryComponentFactory.class, String.class);
/**
* The meta-property for the {@code gangliaTtl} property.
*/
private final MetaProperty<Integer> _gangliaTtl = DirectMetaProperty.ofReadWrite(
this, "gangliaTtl", MetricsRepositoryComponentFactory.class, Integer.class);
/**
* The meta-properties.
*/
private final Map<String, MetaProperty<?>> _metaPropertyMap$ = new DirectMetaPropertyMap(
this, (DirectMetaPropertyMap) super.metaPropertyMap(),
"registryName",
"jmxPublish",
"slf4jPublish",
"gangliaPublish",
"gangliaAddress",
"gangliaPort",
"gangliaAddressingMode",
"gangliaTtl");
/**
* Restricted constructor.
*/
protected Meta() {
}
@Override
protected MetaProperty<?> metaPropertyGet(String propertyName) {
switch (propertyName.hashCode()) {
case -1329285016: // registryName
return _registryName;
case 1313494970: // jmxPublish
return _jmxPublish;
case 283122412: // slf4jPublish
return _slf4jPublish;
case 113968702: // gangliaPublish
return _gangliaPublish;
case -798358237: // gangliaAddress
return _gangliaAddress;
case 44258738: // gangliaPort
return _gangliaPort;
case -772603358: // gangliaAddressingMode
return _gangliaAddressingMode;
case 555621019: // gangliaTtl
return _gangliaTtl;
}
return super.metaPropertyGet(propertyName);
}
@Override
public BeanBuilder<? extends MetricsRepositoryComponentFactory> builder() {
return new DirectBeanBuilder<MetricsRepositoryComponentFactory>(new MetricsRepositoryComponentFactory());
}
@Override
public Class<? extends MetricsRepositoryComponentFactory> beanType() {
return MetricsRepositoryComponentFactory.class;
}
@Override
public Map<String, MetaProperty<?>> metaPropertyMap() {
return _metaPropertyMap$;
}
//-----------------------------------------------------------------------
/**
* The meta-property for the {@code registryName} property.
* @return the meta-property, not null
*/
public final MetaProperty<String> registryName() {
return _registryName;
}
/**
* The meta-property for the {@code jmxPublish} property.
* @return the meta-property, not null
*/
public final MetaProperty<Boolean> jmxPublish() {
return _jmxPublish;
}
/**
* The meta-property for the {@code slf4jPublish} property.
* @return the meta-property, not null
*/
public final MetaProperty<Boolean> slf4jPublish() {
return _slf4jPublish;
}
/**
* The meta-property for the {@code gangliaPublish} property.
* @return the meta-property, not null
*/
public final MetaProperty<Boolean> gangliaPublish() {
return _gangliaPublish;
}
/**
* The meta-property for the {@code gangliaAddress} property.
* @return the meta-property, not null
*/
public final MetaProperty<String> gangliaAddress() {
return _gangliaAddress;
}
/**
* The meta-property for the {@code gangliaPort} property.
* @return the meta-property, not null
*/
public final MetaProperty<Integer> gangliaPort() {
return _gangliaPort;
}
/**
* The meta-property for the {@code gangliaAddressingMode} property.
* @return the meta-property, not null
*/
public final MetaProperty<String> gangliaAddressingMode() {
return _gangliaAddressingMode;
}
/**
* The meta-property for the {@code gangliaTtl} property.
* @return the meta-property, not null
*/
public final MetaProperty<Integer> gangliaTtl() {
return _gangliaTtl;
}
//-----------------------------------------------------------------------
@Override
protected Object propertyGet(Bean bean, String propertyName, boolean quiet) {
switch (propertyName.hashCode()) {
case -1329285016: // registryName
return ((MetricsRepositoryComponentFactory) bean).getRegistryName();
case 1313494970: // jmxPublish
return ((MetricsRepositoryComponentFactory) bean).isJmxPublish();
case 283122412: // slf4jPublish
return ((MetricsRepositoryComponentFactory) bean).isSlf4jPublish();
case 113968702: // gangliaPublish
return ((MetricsRepositoryComponentFactory) bean).isGangliaPublish();
case -798358237: // gangliaAddress
return ((MetricsRepositoryComponentFactory) bean).getGangliaAddress();
case 44258738: // gangliaPort
return ((MetricsRepositoryComponentFactory) bean).getGangliaPort();
case -772603358: // gangliaAddressingMode
return ((MetricsRepositoryComponentFactory) bean).getGangliaAddressingMode();
case 555621019: // gangliaTtl
return ((MetricsRepositoryComponentFactory) bean).getGangliaTtl();
}
return super.propertyGet(bean, propertyName, quiet);
}
@Override
protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) {
switch (propertyName.hashCode()) {
case -1329285016: // registryName
((MetricsRepositoryComponentFactory) bean).setRegistryName((String) newValue);
return;
case 1313494970: // jmxPublish
((MetricsRepositoryComponentFactory) bean).setJmxPublish((Boolean) newValue);
return;
case 283122412: // slf4jPublish
((MetricsRepositoryComponentFactory) bean).setSlf4jPublish((Boolean) newValue);
return;
case 113968702: // gangliaPublish
((MetricsRepositoryComponentFactory) bean).setGangliaPublish((Boolean) newValue);
return;
case -798358237: // gangliaAddress
((MetricsRepositoryComponentFactory) bean).setGangliaAddress((String) newValue);
return;
case 44258738: // gangliaPort
((MetricsRepositoryComponentFactory) bean).setGangliaPort((Integer) newValue);
return;
case -772603358: // gangliaAddressingMode
((MetricsRepositoryComponentFactory) bean).setGangliaAddressingMode((String) newValue);
return;
case 555621019: // gangliaTtl
((MetricsRepositoryComponentFactory) bean).setGangliaTtl((Integer) newValue);
return;
}
super.propertySet(bean, propertyName, newValue, quiet);
}
@Override
protected void validate(Bean bean) {
JodaBeanUtils.notEmpty(((MetricsRepositoryComponentFactory) bean)._registryName, "registryName");
super.validate(bean);
}
}
///CLOVER:ON
//-------------------------- AUTOGENERATED END --------------------------
}