/** * Adds the formatted annotations. * * @param sb the sb * @param indentLevel the indent level */ public void addFormattedAnnotations(StringBuilder sb, int indentLevel) { for (String annotation : annotations) { OutputUtilities.javaIndent(sb, indentLevel); sb.append(annotation); OutputUtilities.newLine(sb); } }
/** * Adds the formatted javadoc. * * @param sb the sb * @param indentLevel the indent level */ public void addFormattedJavadoc(StringBuilder sb, int indentLevel) { for (String javaDocLine : javaDocLines) { OutputUtilities.javaIndent(sb, indentLevel); sb.append(javaDocLine); OutputUtilities.newLine(sb); } }
public String getFormattedContent(int indentLevel) { StringBuilder sb = new StringBuilder(); for (String javaDocLine : javaDocLines) { OutputUtilities.javaIndent(sb, indentLevel); sb.append(javaDocLine); OutputUtilities.newLine(sb); } OutputUtilities.javaIndent(sb, indentLevel); if (isStatic) { sb.append("static "); // $NON-NLS-1$ } sb.append('{'); indentLevel++; ListIterator<String> listIter = bodyLines.listIterator(); while (listIter.hasNext()) { String line = listIter.next(); if (line.startsWith("}")) { // $NON-NLS-1$ indentLevel--; } OutputUtilities.newLine(sb); OutputUtilities.javaIndent(sb, indentLevel); sb.append(line); if ((line.endsWith("{") && !line.startsWith("switch")) // $NON-NLS-1$ //$NON-NLS-2$ || line.endsWith(":")) { // $NON-NLS-1$ indentLevel++; } if (line.startsWith("break")) { // $NON-NLS-1$ // if the next line is '}', then don't outdent if (listIter.hasNext()) { String nextLine = listIter.next(); if (nextLine.startsWith("}")) { // $NON-NLS-1$ indentLevel++; } // set back to the previous element listIter.previous(); } indentLevel--; } } indentLevel--; OutputUtilities.newLine(sb); OutputUtilities.javaIndent(sb, indentLevel); sb.append('}'); return sb.toString(); }
@Override public void addElements(XmlElement parentElement) { XmlElement answer = new XmlElement("update"); // $NON-NLS-1$ answer.addAttribute( new Attribute( "id", //$NON-NLS-1$ introspectedTable.getUpdateByExampleStatementId())); answer.addAttribute(new Attribute("parameterType", "map")); // $NON-NLS-1$ //$NON-NLS-2$ context.getCommentGenerator().addComment(answer); StringBuilder sb = new StringBuilder(); sb.append("update "); // $NON-NLS-1$ sb.append(introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime()); answer.addElement(new TextElement(sb.toString())); // set up for first column sb.setLength(0); sb.append("set "); // $NON-NLS-1$ Iterator<IntrospectedColumn> iter = introspectedTable.getNonBLOBColumns().iterator(); while (iter.hasNext()) { IntrospectedColumn introspectedColumn = iter.next(); sb.append(MyBatis3FormattingUtilities.getAliasedEscapedColumnName(introspectedColumn)); sb.append(" = "); // $NON-NLS-1$ sb.append( MyBatis3FormattingUtilities.getParameterClause( introspectedColumn, "record.")); // $NON-NLS-1$ if (iter.hasNext()) { sb.append(','); } answer.addElement(new TextElement(sb.toString())); // set up for the next column if (iter.hasNext()) { sb.setLength(0); OutputUtilities.xmlIndent(sb, 1); } } answer.addElement(getUpdateByExampleIncludeElement()); if (context .getPlugins() .sqlMapUpdateByExampleWithoutBLOBsElementGenerated(answer, introspectedTable)) { parentElement.addElement(answer); } }
/** * Gets the formatted content. * * @param indentLevel the indent level * @return the formatted content */ public String getFormattedContent(int indentLevel) { StringBuilder sb = new StringBuilder(); addFormattedJavadoc(sb, indentLevel); addFormattedAnnotations(sb, indentLevel); OutputUtilities.javaIndent(sb, indentLevel); sb.append(getVisibility().getValue()); if (isAbstract()) { sb.append("abstract "); // $NON-NLS-1$ } if (isStatic()) { sb.append("static "); // $NON-NLS-1$ } if (isFinal()) { sb.append("final "); // $NON-NLS-1$ } sb.append("class "); // $NON-NLS-1$ sb.append(getType().getShortName()); if (superClass != null) { sb.append(" extends "); // $NON-NLS-1$ sb.append(superClass.getShortName()); } if (superInterfaceTypes.size() > 0) { sb.append(" implements "); // $NON-NLS-1$ boolean comma = false; for (FullyQualifiedJavaType fqjt : superInterfaceTypes) { if (comma) { sb.append(", "); // $NON-NLS-1$ } else { comma = true; } sb.append(fqjt.getShortName()); } } sb.append(" {"); // $NON-NLS-1$ indentLevel++; Iterator<Field> fldIter = fields.iterator(); while (fldIter.hasNext()) { OutputUtilities.newLine(sb); Field field = fldIter.next(); sb.append(field.getFormattedContent(indentLevel)); if (fldIter.hasNext()) { OutputUtilities.newLine(sb); } } if (initializationBlocks.size() > 0) { OutputUtilities.newLine(sb); } Iterator<InitializationBlock> blkIter = initializationBlocks.iterator(); while (blkIter.hasNext()) { OutputUtilities.newLine(sb); InitializationBlock initializationBlock = blkIter.next(); sb.append(initializationBlock.getFormattedContent(indentLevel)); if (blkIter.hasNext()) { OutputUtilities.newLine(sb); } } if (methods.size() > 0) { OutputUtilities.newLine(sb); } Iterator<Method> mtdIter = methods.iterator(); while (mtdIter.hasNext()) { OutputUtilities.newLine(sb); Method method = mtdIter.next(); sb.append(method.getFormattedContent(indentLevel, false)); if (mtdIter.hasNext()) { OutputUtilities.newLine(sb); } } if (innerClasses.size() > 0) { OutputUtilities.newLine(sb); } Iterator<InnerClass> icIter = innerClasses.iterator(); while (icIter.hasNext()) { OutputUtilities.newLine(sb); InnerClass innerClass = icIter.next(); sb.append(innerClass.getFormattedContent(indentLevel)); if (icIter.hasNext()) { OutputUtilities.newLine(sb); } } if (innerEnums.size() > 0) { OutputUtilities.newLine(sb); } Iterator<InnerEnum> ieIter = innerEnums.iterator(); while (ieIter.hasNext()) { OutputUtilities.newLine(sb); InnerEnum innerEnum = ieIter.next(); sb.append(innerEnum.getFormattedContent(indentLevel)); if (ieIter.hasNext()) { OutputUtilities.newLine(sb); } } indentLevel--; OutputUtilities.newLine(sb); OutputUtilities.javaIndent(sb, indentLevel); sb.append('}'); return sb.toString(); }
private InnerClass getGeneratedCriteriaInnerClass(TopLevelClass topLevelClass) { Field field; Method method; InnerClass answer = new InnerClass(FullyQualifiedJavaType.getGeneratedCriteriaInstance()); answer.setVisibility(JavaVisibility.PROTECTED); answer.setStatic(true); answer.setAbstract(true); context.getCommentGenerator().addClassComment(answer, introspectedTable); method = new Method(); method.setVisibility(JavaVisibility.PROTECTED); method.setName("GeneratedCriteria"); // $NON-NLS-1$ method.setConstructor(true); method.addBodyLine("super();"); // $NON-NLS-1$ method.addBodyLine("criteria = new ArrayList<Criterion>();"); // $NON-NLS-1$ answer.addMethod(method); List<String> criteriaLists = new ArrayList<String>(); criteriaLists.add("criteria"); // $NON-NLS-1$ for (IntrospectedColumn introspectedColumn : introspectedTable.getNonBLOBColumns()) { if (stringHasValue(introspectedColumn.getTypeHandler())) { String name = addtypeHandledObjectsAndMethods(introspectedColumn, method, answer); criteriaLists.add(name); } } // now generate the isValid method method = new Method(); method.setVisibility(JavaVisibility.PUBLIC); method.setName("isValid"); // $NON-NLS-1$ method.setReturnType(FullyQualifiedJavaType.getBooleanPrimitiveInstance()); StringBuilder sb = new StringBuilder(); Iterator<String> strIter = criteriaLists.iterator(); sb.append("return "); // $NON-NLS-1$ sb.append(strIter.next()); sb.append(".size() > 0"); // $NON-NLS-1$ if (!strIter.hasNext()) { sb.append(';'); } method.addBodyLine(sb.toString()); while (strIter.hasNext()) { sb.setLength(0); OutputUtilities.javaIndent(sb, 1); sb.append("|| "); // $NON-NLS-1$ sb.append(strIter.next()); sb.append(".size() > 0"); // $NON-NLS-1$ if (!strIter.hasNext()) { sb.append(';'); } method.addBodyLine(sb.toString()); } answer.addMethod(method); // now generate the getAllCriteria method if (criteriaLists.size() > 1) { field = new Field(); field.setName("allCriteria"); // $NON-NLS-1$ field.setType(new FullyQualifiedJavaType("List<Criterion>")); // $NON-NLS-1$ field.setVisibility(JavaVisibility.PROTECTED); answer.addField(field); } method = new Method(); method.setVisibility(JavaVisibility.PUBLIC); method.setName("getAllCriteria"); // $NON-NLS-1$ method.setReturnType(new FullyQualifiedJavaType("List<Criterion>")); // $NON-NLS-1$ if (criteriaLists.size() < 2) { method.addBodyLine("return criteria;"); // $NON-NLS-1$ } else { method.addBodyLine("if (allCriteria == null) {"); // $NON-NLS-1$ method.addBodyLine("allCriteria = new ArrayList<Criterion>();"); // $NON-NLS-1$ strIter = criteriaLists.iterator(); while (strIter.hasNext()) { method.addBodyLine(String.format("allCriteria.addAll(%s);", strIter.next())); // $NON-NLS-1$ } method.addBodyLine("}"); // $NON-NLS-1$ method.addBodyLine("return allCriteria;"); // $NON-NLS-1$ } answer.addMethod(method); // now we need to generate the methods that will be used in the SqlMap // to generate the dynamic where clause topLevelClass.addImportedType(FullyQualifiedJavaType.getNewListInstance()); topLevelClass.addImportedType(FullyQualifiedJavaType.getNewArrayListInstance()); field = new Field(); field.setVisibility(JavaVisibility.PROTECTED); FullyQualifiedJavaType listOfCriterion = new FullyQualifiedJavaType("java.util.List<Criterion>"); // $NON-NLS-1$ field.setType(listOfCriterion); field.setName("criteria"); // $NON-NLS-1$ answer.addField(field); method = new Method(); method.setVisibility(JavaVisibility.PUBLIC); method.setReturnType(field.getType()); method.setName(getGetterMethodName(field.getName(), field.getType())); method.addBodyLine("return criteria;"); // $NON-NLS-1$ answer.addMethod(method); // now add the methods for simplifying the individual field set methods method = new Method(); method.setVisibility(JavaVisibility.PROTECTED); method.setName("addCriterion"); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); // $NON-NLS-1$ method.addBodyLine("if (condition == null) {"); // $NON-NLS-1$ method.addBodyLine( "throw new RuntimeException(\"Value for condition cannot be null\");"); //$NON-NLS-1$ method.addBodyLine("}"); // $NON-NLS-1$ method.addBodyLine("criteria.add(new Criterion(condition));"); // $NON-NLS-1$ if (criteriaLists.size() > 1) { method.addBodyLine("allCriteria = null;"); // $NON-NLS-1$ } answer.addMethod(method); method = new Method(); method.setVisibility(JavaVisibility.PROTECTED); method.setName("addCriterion"); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getObjectInstance(), "value")); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); // $NON-NLS-1$ method.addBodyLine("if (value == null) {"); // $NON-NLS-1$ method.addBodyLine( "throw new RuntimeException(\"Value for \" + property + \" cannot be null\");"); //$NON-NLS-1$ method.addBodyLine("}"); // $NON-NLS-1$ method.addBodyLine("criteria.add(new Criterion(condition, value));"); // $NON-NLS-1$ if (criteriaLists.size() > 1) { method.addBodyLine("allCriteria = null;"); // $NON-NLS-1$ } answer.addMethod(method); method = new Method(); method.setVisibility(JavaVisibility.PROTECTED); method.setName("addCriterion"); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getObjectInstance(), "value1")); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getObjectInstance(), "value2")); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); // $NON-NLS-1$ method.addBodyLine("if (value1 == null || value2 == null) {"); // $NON-NLS-1$ method.addBodyLine( "throw new RuntimeException(\"Between values for \" + property + \" cannot be null\");"); //$NON-NLS-1$ method.addBodyLine("}"); // $NON-NLS-1$ method.addBodyLine("criteria.add(new Criterion(condition, value1, value2));"); // $NON-NLS-1$ if (criteriaLists.size() > 1) { method.addBodyLine("allCriteria = null;"); // $NON-NLS-1$ } answer.addMethod(method); FullyQualifiedJavaType listOfDates = new FullyQualifiedJavaType("java.util.List<java.util.Date>"); // $NON-NLS-1$ if (introspectedTable.hasJDBCDateColumns()) { topLevelClass.addImportedType(FullyQualifiedJavaType.getDateInstance()); topLevelClass.addImportedType(FullyQualifiedJavaType.getNewIteratorInstance()); method = new Method(); method.setVisibility(JavaVisibility.PROTECTED); method.setName("addCriterionForJDBCDate"); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getDateInstance(), "value")); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); // $NON-NLS-1$ method.addBodyLine("if (value == null) {"); // $NON-NLS-1$ method.addBodyLine( "throw new RuntimeException(\"Value for \" + property + \" cannot be null\");"); //$NON-NLS-1$ method.addBodyLine("}"); // $NON-NLS-1$ method.addBodyLine( "addCriterion(condition, new java.sql.Date(value.getTime()), property);"); //$NON-NLS-1$ answer.addMethod(method); method = new Method(); method.setVisibility(JavaVisibility.PROTECTED); method.setName("addCriterionForJDBCDate"); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); // $NON-NLS-1$ method.addParameter(new Parameter(listOfDates, "values")); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); // $NON-NLS-1$ method.addBodyLine("if (values == null || values.size() == 0) {"); // $NON-NLS-1$ method.addBodyLine( "throw new RuntimeException(\"Value list for \" + property + \" cannot be null or empty\");"); //$NON-NLS-1$ method.addBodyLine("}"); // $NON-NLS-1$ method.addBodyLine( "List<java.sql.Date> dateList = new ArrayList<java.sql.Date>();"); //$NON-NLS-1$ method.addBodyLine("Iterator<Date> iter = values.iterator();"); // $NON-NLS-1$ method.addBodyLine("while (iter.hasNext()) {"); // $NON-NLS-1$ method.addBodyLine("dateList.add(new java.sql.Date(iter.next().getTime()));"); // $NON-NLS-1$ method.addBodyLine("}"); // $NON-NLS-1$ method.addBodyLine("addCriterion(condition, dateList, property);"); // $NON-NLS-1$ answer.addMethod(method); method = new Method(); method.setVisibility(JavaVisibility.PROTECTED); method.setName("addCriterionForJDBCDate"); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getDateInstance(), "value1")); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getDateInstance(), "value2")); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); // $NON-NLS-1$ method.addBodyLine("if (value1 == null || value2 == null) {"); // $NON-NLS-1$ method.addBodyLine( "throw new RuntimeException(\"Between values for \" + property + \" cannot be null\");"); //$NON-NLS-1$ method.addBodyLine("}"); // $NON-NLS-1$ method.addBodyLine( "addCriterion(condition, new java.sql.Date(value1.getTime()), new java.sql.Date(value2.getTime()), property);"); //$NON-NLS-1$ answer.addMethod(method); } if (introspectedTable.hasJDBCTimeColumns()) { topLevelClass.addImportedType(FullyQualifiedJavaType.getDateInstance()); topLevelClass.addImportedType(FullyQualifiedJavaType.getNewIteratorInstance()); method = new Method(); method.setVisibility(JavaVisibility.PROTECTED); method.setName("addCriterionForJDBCTime"); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getDateInstance(), "value")); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); // $NON-NLS-1$ method.addBodyLine("if (value == null) {"); // $NON-NLS-1$ method.addBodyLine( "throw new RuntimeException(\"Value for \" + property + \" cannot be null\");"); //$NON-NLS-1$ method.addBodyLine("}"); // $NON-NLS-1$ method.addBodyLine( "addCriterion(condition, new java.sql.Time(value.getTime()), property);"); //$NON-NLS-1$ answer.addMethod(method); method = new Method(); method.setVisibility(JavaVisibility.PROTECTED); method.setName("addCriterionForJDBCTime"); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); // $NON-NLS-1$ method.addParameter(new Parameter(listOfDates, "values")); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); // $NON-NLS-1$ method.addBodyLine("if (values == null || values.size() == 0) {"); // $NON-NLS-1$ method.addBodyLine( "throw new RuntimeException(\"Value list for \" + property + \" cannot be null or empty\");"); //$NON-NLS-1$ method.addBodyLine("}"); // $NON-NLS-1$ method.addBodyLine( "List<java.sql.Time> timeList = new ArrayList<java.sql.Time>();"); //$NON-NLS-1$ method.addBodyLine("Iterator<Date> iter = values.iterator();"); // $NON-NLS-1$ method.addBodyLine("while (iter.hasNext()) {"); // $NON-NLS-1$ method.addBodyLine("timeList.add(new java.sql.Time(iter.next().getTime()));"); // $NON-NLS-1$ method.addBodyLine("}"); // $NON-NLS-1$ method.addBodyLine("addCriterion(condition, timeList, property);"); // $NON-NLS-1$ answer.addMethod(method); method = new Method(); method.setVisibility(JavaVisibility.PROTECTED); method.setName("addCriterionForJDBCTime"); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getStringInstance(), "condition")); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getDateInstance(), "value1")); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getDateInstance(), "value2")); // $NON-NLS-1$ method.addParameter( new Parameter(FullyQualifiedJavaType.getStringInstance(), "property")); // $NON-NLS-1$ method.addBodyLine("if (value1 == null || value2 == null) {"); // $NON-NLS-1$ method.addBodyLine( "throw new RuntimeException(\"Between values for \" + property + \" cannot be null\");"); //$NON-NLS-1$ method.addBodyLine("}"); // $NON-NLS-1$ method.addBodyLine( "addCriterion(condition, new java.sql.Time(value1.getTime()), new java.sql.Time(value2.getTime()), property);"); //$NON-NLS-1$ answer.addMethod(method); } for (IntrospectedColumn introspectedColumn : introspectedTable.getNonBLOBColumns()) { topLevelClass.addImportedType(introspectedColumn.getFullyQualifiedJavaType()); // here we need to add the individual methods for setting the // conditions for a field answer.addMethod(getSetNullMethod(introspectedColumn)); answer.addMethod(getSetNotNullMethod(introspectedColumn)); answer.addMethod(getSetEqualMethod(introspectedColumn)); answer.addMethod(getSetNotEqualMethod(introspectedColumn)); answer.addMethod(getSetGreaterThanMethod(introspectedColumn)); answer.addMethod(getSetGreaterThenOrEqualMethod(introspectedColumn)); answer.addMethod(getSetLessThanMethod(introspectedColumn)); answer.addMethod(getSetLessThanOrEqualMethod(introspectedColumn)); if (introspectedColumn.isJdbcCharacterColumn()) { answer.addMethod(getSetLikeMethod(introspectedColumn)); answer.addMethod(getSetNotLikeMethod(introspectedColumn)); } answer.addMethod(getSetInOrNotInMethod(introspectedColumn, true)); answer.addMethod(getSetInOrNotInMethod(introspectedColumn, false)); answer.addMethod(getSetBetweenOrNotBetweenMethod(introspectedColumn, true)); answer.addMethod(getSetBetweenOrNotBetweenMethod(introspectedColumn, false)); } return answer; }
@Override public void addElements(XmlElement parentElement) { XmlElement answer = new XmlElement("update"); // $NON-NLS-1$ answer.addAttribute( new Attribute("id", introspectedTable.getUpdateByPrimaryKeyStatementId())); // $NON-NLS-1$ answer.addAttribute( new Attribute( "parameterType", //$NON-NLS-1$ introspectedTable.getBaseRecordType())); context.getCommentGenerator().addComment(answer); StringBuilder sb = new StringBuilder(); sb.append("update "); // $NON-NLS-1$ sb.append(introspectedTable.getFullyQualifiedTableNameAtRuntime()); answer.addElement(new TextElement(sb.toString())); // set up for first column sb.setLength(0); sb.append("set "); // $NON-NLS-1$ Iterator<IntrospectedColumn> iter; if (isSimple) { iter = introspectedTable.getNonPrimaryKeyColumns().iterator(); } else { iter = introspectedTable.getBaseColumns().iterator(); } while (iter.hasNext()) { IntrospectedColumn introspectedColumn = iter.next(); sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn)); sb.append(" = "); // $NON-NLS-1$ sb.append(MyBatis3FormattingUtilities.getParameterClause(introspectedColumn)); if (iter.hasNext()) { sb.append(','); } answer.addElement(new TextElement(sb.toString())); // set up for the next column if (iter.hasNext()) { sb.setLength(0); OutputUtilities.xmlIndent(sb, 1); } } boolean and = false; for (IntrospectedColumn introspectedColumn : introspectedTable.getPrimaryKeyColumns()) { sb.setLength(0); if (and) { sb.append(" and "); // $NON-NLS-1$ } else { sb.append("where "); // $NON-NLS-1$ and = true; } sb.append(MyBatis3FormattingUtilities.getEscapedColumnName(introspectedColumn)); sb.append(" = "); // $NON-NLS-1$ sb.append(MyBatis3FormattingUtilities.getParameterClause(introspectedColumn)); answer.addElement(new TextElement(sb.toString())); } if (context .getPlugins() .sqlMapUpdateByPrimaryKeyWithoutBLOBsElementGenerated(answer, introspectedTable)) { parentElement.addElement(answer); } }