Example usage for java.lang Class getConstructors

List of usage examples for java.lang Class getConstructors

Introduction

In this page you can find the example usage for java.lang Class getConstructors.

Prototype

@CallerSensitive
public Constructor<?>[] getConstructors() throws SecurityException 

Source Link

Document

Returns an array containing Constructor objects reflecting all the public constructors of the class represented by this Class object.

Usage

From source file:com.medallia.spider.SpiderServlet.java

/** @return an instance of the task the given URI maps to, or null if no such class exists */
private ITask findTask(String uri, RequestHandler request) {
    String tn = extractTaskName(uri);
    if (tn != null) {
        String cn = taskPackage + tn;
        Class<?> c;
        try {/*from w  ww  .j a va  2  s  . c o m*/
            c = Class.forName(cn);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("No class " + cn);
        }
        if (c != null && ITask.class.isAssignableFrom(c)) {
            @SuppressWarnings({ "unchecked" })
            Constructor<ITask>[] consArr = (Constructor<ITask>[]) c.getConstructors();
            if (consArr.length != 1)
                throw new RuntimeException("Class " + c + " must have exactly one constructor");
            return new MethodInvoker(makeObjectProvider(request), makeLifecycleHandlerSet(request))
                    .invoke(consArr[0]);
        }
    }
    return null;
}

From source file:org.elasticsoftware.elasticactors.base.serialization.ObjectMapperBuilder.java

private void registerCustomDeserializers(Reflections reflections, SimpleModule jacksonModule) {
    // @todo: looks like the SubTypeScanner only goes one level deep, need to fix this
    Set<Class<? extends StdScalarDeserializer>> customDeserializers = reflections
            .getSubTypesOf(StdScalarDeserializer.class);
    for (Class<? extends StdScalarDeserializer> customDeserializer : customDeserializers) {
        // need to exclude the JacksonActorRefDeserializer
        if (hasNoArgConstructor(customDeserializer)) {
            try {
                StdScalarDeserializer deserializer = customDeserializer.newInstance();
                Class<?> objectClass = deserializer.handledType();
                jacksonModule.addDeserializer(objectClass, deserializer);
            } catch (Exception e) {
                logger.error(String.format("Failed to create Custom Jackson Deserializer: %s",
                        customDeserializer.getName()), e);
            }//from ww w  . j a va 2s. c  om
        } else {
            // this ones can currently not be created by the scanner due to the special constructor
            for (Constructor<?> constructor : customDeserializer.getConstructors()) {
                if (hasSingleConstrutorParameterMatching(constructor, ActorRefFactory.class)) {
                    try {
                        StdScalarDeserializer deserializer = (StdScalarDeserializer) constructor
                                .newInstance(actorRefFactory);
                        Class<?> objectClass = deserializer.handledType();
                        jacksonModule.addDeserializer(objectClass, deserializer);
                        break;
                    } catch (Exception e) {
                        logger.error(String.format("Failed to create Custom Jackson Deserializer: %s",
                                customDeserializer.getName()), e);
                    }
                } else if (hasSingleConstrutorParameterMatching(constructor,
                        ScheduledMessageRefFactory.class)) {
                    try {
                        StdScalarDeserializer deserializer = (StdScalarDeserializer) constructor
                                .newInstance(scheduledMessageRefFactory);
                        Class<?> objectClass = deserializer.handledType();
                        jacksonModule.addDeserializer(objectClass, deserializer);
                        break;
                    } catch (Exception e) {
                        logger.error(String.format("Failed to create Custom Jackson Deserializer: %s",
                                customDeserializer.getName()), e);
                    }
                }
            }

        }
    }
}

From source file:org.eclipse.emf.teneo.extension.DefaultExtensionManager.java

/** Return the constructor for a class and initialization arguments */
protected Constructor<?> getConstructor(Class<?> clz, Object[] initArgs) throws NoSuchMethodException {
    Constructor<?> result = null;
    final Class<?>[] initTypes = new Class<?>[initArgs.length];
    int i = 0;/*from  w w w .jav  a  2  s .c o  m*/
    final StringBuffer keyStr = new StringBuffer();
    for (Object o : initArgs) {
        if (keyStr.length() > 0) {
            keyStr.append(",");
        }
        if (o == null) {
            initTypes[i++] = null;
            keyStr.append("null");
        } else {
            initTypes[i++] = o.getClass();
            keyStr.append(o.getClass().getName());
        }
    }

    final String key = clz.getName() + keyStr;

    if ((result = constructorCache.get(key)) != null) {
        return result;
    }

    for (Constructor<?> constructor : clz.getConstructors()) {
        if (constructor.getParameterTypes().length != initTypes.length) {
            continue;
        }
        int j = 0;
        boolean found = true;
        for (Class<?> paramType : constructor.getParameterTypes()) {
            final Class<?> argumentType = initTypes[j++];
            if (argumentType == null && !Object.class.isAssignableFrom(paramType)) {
                found = false;
                break;
            } else if (argumentType == null && Object.class.isAssignableFrom(paramType)) {
                // just continue
            } else if (!paramType.isAssignableFrom(argumentType)) {
                found = false;
                break;
            }
        }
        if (found) {
            result = constructor;
            constructorCache.put(key, result);
            break;
        }
    }
    if (result == null) {
        throw new TeneoExtensionException(
                "No constructor found for : " + clz.getName() + " and constructor argument types: " + keyStr);
    }
    return result;
}

From source file:org.apache.hadoop.hbase.PerformanceEvaluation.java

static long runOneClient(final Class<? extends Test> cmd, Configuration conf, TestOptions opts,
        final Status status) throws IOException {
    status.setStatus(/*from ww  w . j a va 2 s . c  o  m*/
            "Start " + cmd + " at offset " + opts.startRow + " for " + opts.perClientRunRows + " rows");
    long totalElapsedTime;

    final Test t;
    try {
        Constructor<? extends Test> constructor = cmd.getDeclaredConstructor(Configuration.class,
                TestOptions.class, Status.class);
        t = constructor.newInstance(conf, opts, status);
    } catch (NoSuchMethodException e) {
        throw new IllegalArgumentException("Invalid command class: " + cmd.getName()
                + ".  It does not provide a constructor as described by "
                + "the javadoc comment.  Available constructors are: "
                + Arrays.toString(cmd.getConstructors()));
    } catch (Exception e) {
        throw new IllegalStateException("Failed to construct command class", e);
    }
    totalElapsedTime = t.test();

    status.setStatus("Finished " + cmd + " in " + totalElapsedTime + "ms at offset " + opts.startRow + " for "
            + opts.perClientRunRows + " rows" + " ("
            + calculateMbps((int) (opts.perClientRunRows * opts.sampleRate), totalElapsedTime) + ")");
    return totalElapsedTime;
}

From source file:com.opensymphony.xwork2.util.finder.DefaultClassFinder.java

public DefaultClassFinder(List<Class> classes) {
    this.classLoaderInterface = null;
    List<Info> infos = new ArrayList<Info>();
    List<Package> packages = new ArrayList<Package>();
    for (Class clazz : classes) {

        Package aPackage = clazz.getPackage();
        if (aPackage != null && !packages.contains(aPackage)) {
            infos.add(new PackageInfo(aPackage));
            packages.add(aPackage);/* www  .  ja  v  a2s .  c om*/
        }

        ClassInfo classInfo = new ClassInfo(clazz, this);
        infos.add(classInfo);
        classInfos.put(classInfo.getName(), classInfo);
        for (Method method : clazz.getDeclaredMethods()) {
            infos.add(new MethodInfo(classInfo, method));
        }

        for (Constructor constructor : clazz.getConstructors()) {
            infos.add(new MethodInfo(classInfo, constructor));
        }

        for (Field field : clazz.getDeclaredFields()) {
            infos.add(new FieldInfo(classInfo, field));
        }
    }

    for (Info info : infos) {
        for (AnnotationInfo annotation : info.getAnnotations()) {
            List<Info> annotationInfos = getAnnotationInfos(annotation.getName());
            annotationInfos.add(info);
        }
    }
}

From source file:org.apache.struts2.convention.Java8ClassFinder.java

public Java8ClassFinder(List<Class> classes) {
    this.classLoaderInterface = null;
    List<Info> infos = new ArrayList<Info>();
    List<Package> packages = new ArrayList<Package>();
    for (Class clazz : classes) {

        Package aPackage = clazz.getPackage();
        if (aPackage != null && !packages.contains(aPackage)) {
            infos.add(new PackageInfo(aPackage));
            packages.add(aPackage);//ww w  .jav  a  2  s.co m
        }

        ClassInfo classInfo = new ClassInfo(clazz, this);
        infos.add(classInfo);
        classInfos.put(classInfo.getName(), classInfo);
        for (Method method : clazz.getDeclaredMethods()) {
            infos.add(new MethodInfo(classInfo, method));
        }

        for (Constructor constructor : clazz.getConstructors()) {
            infos.add(new MethodInfo(classInfo, constructor));
        }

        for (Field field : clazz.getDeclaredFields()) {
            infos.add(new FieldInfo(classInfo, field));
        }
    }

    for (Info info : infos) {
        for (AnnotationInfo annotation : info.getAnnotations()) {
            List<Info> annotationInfos = getAnnotationInfos(annotation.getName());
            annotationInfos.add(info);
        }
    }
}

From source file:org.apache.struts2.convention.DefaultClassFinder.java

public DefaultClassFinder(List<Class> classes) {
    this.classLoaderInterface = null;
    List<Info> infos = new ArrayList<>();
    List<Package> packages = new ArrayList<>();
    for (Class clazz : classes) {

        Package aPackage = clazz.getPackage();
        if (aPackage != null && !packages.contains(aPackage)) {
            infos.add(new PackageInfo(aPackage));
            packages.add(aPackage);//from   w  w  w .j a  va 2 s  .  c  o  m
        }

        ClassInfo classInfo = new ClassInfo(clazz, this);
        infos.add(classInfo);
        classInfos.put(classInfo.getName(), classInfo);
        for (Method method : clazz.getDeclaredMethods()) {
            infos.add(new MethodInfo(classInfo, method));
        }

        for (Constructor constructor : clazz.getConstructors()) {
            infos.add(new MethodInfo(classInfo, constructor));
        }

        for (Field field : clazz.getDeclaredFields()) {
            infos.add(new FieldInfo(classInfo, field));
        }
    }

    for (Info info : infos) {
        for (AnnotationInfo annotation : info.getAnnotations()) {
            List<Info> annotationInfos = getAnnotationInfos(annotation.getName());
            annotationInfos.add(info);
        }
    }
}

From source file:com.amossys.hooker.hookers.Hooker.java

protected void hookMethodsWithOutputs(final HookerListener listener, final String className,
        final Map<String, Integer> methods, final Map<String, Object> outputs)
        throws HookerInitializationException {

    final String hookerName = this.getHookerName();

    MS.hookClassLoad(className, new MS.ClassLoadHook() {

        @SuppressWarnings({ "unchecked", "rawtypes" })
        public void classLoaded(Class<?> resources) {

            /**/* www.ja  v a2 s . c  o m*/
             * Based on the name of the method, we retrieve all the possibilities
             */
            Map<GenericDeclaration, String> methodsToHook = new HashMap<GenericDeclaration, String>();
            boolean found;
            for (String methodName : methods.keySet()) {
                found = false;

                /**
                 * Checks if the requested method is a constructor or not
                 */
                if (className.substring(className.lastIndexOf('.') + 1).equals(methodName)) {
                    found = true;
                    for (int iConstructor = 0; iConstructor < resources
                            .getConstructors().length; iConstructor++) {
                        methodsToHook.put(resources.getConstructors()[iConstructor], methodName);
                    }
                } else {
                    for (Method m : resources.getMethods()) {
                        if (m.getName().equals(methodName)) {
                            found = true;
                            methodsToHook.put(m, methodName);
                        }
                    }
                }
                if (!found) {
                    SubstrateMain.log(new StringBuilder("No method found with name ").append(className)
                            .append(":").append(methodName).toString());
                }
            }

            for (final GenericDeclaration pMethod : methodsToHook.keySet()) {
                final String methodName = methodsToHook.get(pMethod);
                if (SubstrateMain.DEBUG_MODE) {
                    SubstrateMain.log(new StringBuilder("Hooking method ").append(className).append(":")
                            .append(methodName).toString());
                }

                // To debug Substrate if you have a stacktrace
                // for (Class param : ((Method) pMethod).getParameterTypes()) {
                // SubstrateMain.log("   Param: " + param.getSimpleName());
                // }

                final int intrusiveLevelFinal = methods.get(methodName);

                final MS.MethodPointer<Object, Object> old = new MethodPointer<Object, Object>();
                MS.hookMethod_(resources, (Member) pMethod, new MS.MethodHook() {
                    public Object invoked(final Object resources, final Object... args) throws Throwable {

                        if (ApplicationConfig.isFiltered() || ApplicationConfig.getPackageName() == null) {
                            return old.invoke(resources, args);
                        }

                        if (isSelfHooking((Member) pMethod)) {
                            SubstrateMain.log(
                                    "Self hooking detected on method '" + ((Member) pMethod).getName() + "'.");
                            return old.invoke(resources, args);
                        }

                        final String packName = ApplicationConfig.getPackageName();
                        final Context appContext = ApplicationConfig.getContext();

                        InterceptEvent event = null;

                        if (packName != null && appContext != null) {

                            // Open the connection to the service if not yet bound
                            if (!serviceConnection.isBoundToTheService()) {
                                serviceConnection.doBindService(appContext);
                            }

                            // Create the intercept event for this hook
                            event = new InterceptEvent(hookerName, intrusiveLevelFinal,
                                    System.identityHashCode(resources), packName, className, methodName);

                            //TODO: We should also save the parameters value before the call.
                            //      it requires to clone the parameters
                            //      and save them in the event if their value is different after the call

                            /**
                             * If specified, we execute the before method of the provided listener
                             */
                            if (listener != null) {
                                listener.before(className, pMethod, resources, event);
                            }

                        }

                        /**
                         * We invoke the original method and capture the result
                         */
                        Object result = old.invoke(resources, args);

                        // if requested we modify the output value of the invocation
                        if (outputs != null && outputs.containsKey(methodName)) {

                            if (result == null || outputs.get(methodName) == null
                                    || result.getClass().isAssignableFrom(outputs.get(methodName).getClass())) {
                                result = outputs.get(methodName);
                            } else {
                                SubstrateMain.log("Cannot replace method " + methodName + " output with "
                                        + outputs.get(methodName) + ": types are incompatible.", false);
                            }
                        }

                        // Store the result in the event (if available)
                        if (event != null && appContext != null) {

                            // Register the parameters of the method call in the event
                            if (args != null) {
                                for (Object arg : args) {
                                    if (arg != null) {
                                        String argValue = getStringRepresentationOfAttribute(arg);
                                        event.addParameter(arg.getClass().getName(), argValue);
                                    } else {
                                        event.addParameter(null, null);
                                    }
                                }
                            }

                            // if the invocation returned something we store it in the event
                            if (result != null) {
                                String strResult = getStringRepresentationOfAttribute(result);
                                event.setReturns(result.getClass().getName(), strResult);
                            } else {
                                event.setReturns(null, null);
                            }

                            /**
                             * if specified, we execute the after method of the provided listener
                             */
                            if (listener != null) {
                                listener.after(className, pMethod, resources, event);
                            }

                            insertEvent(event, appContext);
                        }

                        return result;
                    }

                    /**
                     * Computes if we are self hooking ourselves. To do so, we generate a stack trace to retrieve
                     * the caller list of the current invocation and check no Hooker appears after the second entry of the stack trace.
                     * @param pMethod 
                     * @param pMethod 
                     * @return true if we are self-hooking
                     */
                    private boolean isSelfHooking(Member pMethod) {
                        boolean selfHooking = false;
                        StackTraceElement[] stackTrace = new Throwable().getStackTrace();
                        if (stackTrace.length > 2) {
                            for (int i = 2; i < stackTrace.length; i++) {
                                if (stackTrace[i].getClassName().startsWith(Hooker.class.getName())) {
                                    selfHooking = true;
                                    break;
                                }
                            }
                        }
                        return selfHooking;
                    }

                }, old);
            }

        }
    });

}

From source file:org.apache.poi.util.MethodUtils.java

public static <T> Constructor<T> getMatchingAccessibleConstructor(Class<T> clazz, Class[] parameterTypes) {
    // trace logging
    Log log = LogFactory.getLog(MethodUtils.class);
    MethodDescriptor md = new MethodDescriptor(clazz, "dummy", parameterTypes, false);

    // see if we can find the method directly
    // most of the time this works and it's much faster
    try {/*from   ww w . ja v  a 2s .  co  m*/
        Constructor<T> constructor = clazz.getConstructor(parameterTypes);
        if (log.isTraceEnabled()) {
            log.trace("Found straight match: " + constructor);
            log.trace("isPublic:" + Modifier.isPublic(constructor.getModifiers()));
        }

        setMethodAccessible(constructor); // Default access superclass workaround

        return constructor;

    } catch (NoSuchMethodException e) {
        /* SWALLOW */ }

    // search through all methods 
    int paramSize = parameterTypes.length;
    Constructor<T> bestMatch = null;
    Constructor<?>[] constructors = clazz.getConstructors();
    float bestMatchCost = Float.MAX_VALUE;
    float myCost = Float.MAX_VALUE;
    for (int i = 0, size = constructors.length; i < size; i++) {
        // compare parameters
        Class[] methodsParams = constructors[i].getParameterTypes();
        int methodParamSize = methodsParams.length;
        if (methodParamSize == paramSize) {
            boolean match = true;
            for (int n = 0; n < methodParamSize; n++) {
                if (log.isTraceEnabled()) {
                    log.trace("Param=" + parameterTypes[n].getName());
                    log.trace("Method=" + methodsParams[n].getName());
                }
                if (!isAssignmentCompatible(methodsParams[n], parameterTypes[n])) {
                    if (log.isTraceEnabled()) {
                        log.trace(methodsParams[n] + " is not assignable from " + parameterTypes[n]);
                    }
                    match = false;
                    break;
                }
            }

            if (match) {
                // get accessible version of method
                Constructor<T> cons = (Constructor<T>) constructors[i];
                myCost = getTotalTransformationCost(parameterTypes, cons.getParameterTypes());
                if (myCost < bestMatchCost) {
                    bestMatch = cons;
                    bestMatchCost = myCost;
                }
            }
        }
    }
    if (bestMatch == null) {
        // didn't find a match
        log.trace("No match found.");
    }

    return bestMatch;
}

From source file:de.escalon.hypermedia.spring.hydra.LinkListSerializer.java

/**
 * Writes bean description recursively./*from  w  ww.  j  av a  2s. co  m*/
 *
 * @param jgen
 *         to write to
 * @param currentVocab
 *         in context
 * @param valueType
 *         class of value
 * @param allRootParameters
 *         of the method that receives the request body
 * @param rootParameter
 *         the request body
 * @param currentCallValue
 *         the value at the current recursion level
 * @param propertyPath
 *         of the current recursion level
 * @throws IntrospectionException
 * @throws IOException
 */
private void recurseSupportedProperties(JsonGenerator jgen, String currentVocab, Class<?> valueType,
        ActionDescriptor allRootParameters, ActionInputParameter rootParameter, Object currentCallValue,
        String propertyPath) throws IntrospectionException, IOException {

    Map<String, ActionInputParameter> properties = new HashMap<String, ActionInputParameter>();

    // collect supported properties from ctor

    Constructor[] constructors = valueType.getConstructors();
    // find default ctor
    Constructor constructor = PropertyUtils.findDefaultCtor(constructors);
    // find ctor with JsonCreator ann
    if (constructor == null) {
        constructor = PropertyUtils.findJsonCreator(constructors, JsonCreator.class);
    }
    if (constructor == null) {
        // TODO this can be a generic collection, find a way to describe it
        LOG.warn("can't describe supported properties, no default constructor or JsonCreator found for type "
                + valueType.getName());
        return;
    }

    int parameterCount = constructor.getParameterTypes().length;
    if (parameterCount > 0) {
        Annotation[][] annotationsOnParameters = constructor.getParameterAnnotations();

        Class[] parameters = constructor.getParameterTypes();
        int paramIndex = 0;
        for (Annotation[] annotationsOnParameter : annotationsOnParameters) {
            for (Annotation annotation : annotationsOnParameter) {
                if (JsonProperty.class == annotation.annotationType()) {
                    JsonProperty jsonProperty = (JsonProperty) annotation;
                    // TODO use required attribute of JsonProperty
                    String paramName = jsonProperty.value();

                    Object propertyValue = PropertyUtils.getPropertyOrFieldValue(currentCallValue, paramName);

                    ActionInputParameter constructorParamInputParameter = new SpringActionInputParameter(
                            new MethodParameter(constructor, paramIndex), propertyValue);

                    // TODO collect ctor params, setter params and process
                    // TODO then handle single, collection and bean for both
                    properties.put(paramName, constructorParamInputParameter);
                    paramIndex++; // increase for each @JsonProperty
                }
            }
        }
        Assert.isTrue(parameters.length == paramIndex, "not all constructor arguments of @JsonCreator "
                + constructor.getName() + " are annotated with @JsonProperty");
    }

    // collect supported properties from setters

    // TODO support Option provider by other method args?
    final BeanInfo beanInfo = Introspector.getBeanInfo(valueType);
    final PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
    // TODO collection and map
    // TODO distinguish which properties should be printed as supported - now just setters
    for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
        final Method writeMethod = propertyDescriptor.getWriteMethod();
        if (writeMethod == null) {
            continue;
        }
        // TODO: the property name must be a valid URI - need to check context for terms?
        String propertyName = getWritableExposedPropertyOrPropertyName(propertyDescriptor);

        Object propertyValue = PropertyUtils.getPropertyOrFieldValue(currentCallValue,
                propertyDescriptor.getName());

        MethodParameter methodParameter = new MethodParameter(propertyDescriptor.getWriteMethod(), 0);
        ActionInputParameter propertySetterInputParameter = new SpringActionInputParameter(methodParameter,
                propertyValue);

        properties.put(propertyName, propertySetterInputParameter);
    }

    // write all supported properties
    // TODO we are using the annotatedParameter.parameterName but should use the key of properties here:
    for (ActionInputParameter annotatedParameter : properties.values()) {
        String nextPropertyPathLevel = propertyPath.isEmpty() ? annotatedParameter.getParameterName()
                : propertyPath + '.' + annotatedParameter.getParameterName();
        if (DataType.isSingleValueType(annotatedParameter.getParameterType())) {

            final Object[] possiblePropertyValues = rootParameter.getPossibleValues(allRootParameters);

            if (rootParameter.isIncluded(nextPropertyPathLevel)
                    && !rootParameter.isExcluded(nextPropertyPathLevel)) {
                writeSupportedProperty(jgen, currentVocab, annotatedParameter,
                        annotatedParameter.getParameterName(), possiblePropertyValues);
            }
            // TODO collections?
            //                        } else if (DataType.isArrayOrCollection(parameterType)) {
            //                            Object[] callValues = rootParameter.getValues();
            //                            int items = callValues.length;
            //                            for (int i = 0; i < items; i++) {
            //                                Object value;
            //                                if (i < callValues.length) {
            //                                    value = callValues[i];
            //                                } else {
            //                                    value = null;
            //                                }
            //                                recurseSupportedProperties(jgen, currentVocab, rootParameter
            // .getParameterType(),
            //                                        allRootParameters, rootParameter, value);
            //                            }
        } else {
            jgen.writeStartObject();
            jgen.writeStringField("hydra:property", annotatedParameter.getParameterName());
            // TODO: is the property required -> for bean props we need the Access annotation to express that
            jgen.writeObjectFieldStart(getPropertyOrClassNameInVocab(currentVocab, "rangeIncludes",
                    LdContextFactory.HTTP_SCHEMA_ORG, "schema:"));
            Expose expose = AnnotationUtils.getAnnotation(annotatedParameter.getParameterType(), Expose.class);
            String subClass;
            if (expose != null) {
                subClass = expose.value();
            } else {
                subClass = annotatedParameter.getParameterType().getSimpleName();
            }
            jgen.writeStringField(getPropertyOrClassNameInVocab(currentVocab, "subClassOf",
                    "http://www.w3" + ".org/2000/01/rdf-schema#", "rdfs:"), subClass);

            jgen.writeArrayFieldStart("hydra:supportedProperty");

            Object propertyValue = PropertyUtils.getPropertyOrFieldValue(currentCallValue,
                    annotatedParameter.getParameterName());

            recurseSupportedProperties(jgen, currentVocab, annotatedParameter.getParameterType(),
                    allRootParameters, rootParameter, propertyValue, nextPropertyPathLevel);
            jgen.writeEndArray();

            jgen.writeEndObject();
            jgen.writeEndObject();
        }
    }
}