public void testInsertableUpdateableHibernateMapping() throws Exception {
    GroovyClassLoader cl = new GroovyClassLoader();
    GrailsDomainClass domainClass =
        new DefaultGrailsDomainClass(
            cl.parseClass(
                "class TestInsertableUpdateableDomain {\n"
                    + "    Long id \n"
                    + "    Long version \n"
                    + "    String testString1 \n"
                    + "    String testString2 \n"
                    + "\n"
                    + "    static mapping = {\n"
                    + "       testString1 insertable:false, updateable:false \n"
                    + "       testString2 updateable:false, insertable:false \n"
                    + "    }\n"
                    + "}"));

    DefaultGrailsDomainConfiguration config =
        getDomainConfig(cl, new Class[] {domainClass.getClazz()});

    PersistentClass persistentClass = config.getClassMapping("TestInsertableUpdateableDomain");

    Property property1 = persistentClass.getProperty("testString1");
    assertEquals(false, property1.isInsertable());
    assertEquals(false, property1.isUpdateable());

    Property property2 = persistentClass.getProperty("testString2");
    assertEquals(false, property2.isUpdateable());
    assertEquals(false, property2.isInsertable());
  }
  @Deprecated
  public static StandardProperty buildStandardProperty(Property property, boolean lazyAvailable) {
    final Type type = property.getValue().getType();

    // we need to dirty check collections, since they can cause an owner
    // version number increment

    // we need to dirty check many-to-ones with not-found="ignore" in order
    // to update the cache (not the database), since in this case a null
    // entity reference can lose information

    boolean alwaysDirtyCheck =
        type.isAssociationType() && ((AssociationType) type).isAlwaysDirtyChecked();

    return new StandardProperty(
        property.getName(),
        type,
        lazyAvailable && property.isLazy(),
        property.isInsertable(),
        property.isUpdateable(),
        property.getValueGenerationStrategy(),
        property.isOptional(),
        alwaysDirtyCheck || property.isUpdateable(),
        property.isOptimisticLocked(),
        property.getCascadeStyle(),
        property.getValue().getFetchMode());
  }
  /**
   * Generates a VersionProperty representation for an entity mapping given its version mapping
   * Property.
   *
   * @param property The version mapping Property.
   * @param lazyAvailable Is property lazy loading currently available.
   * @return The appropriate VersionProperty definition.
   */
  public static VersionProperty buildVersionProperty(
      EntityPersister persister,
      SessionFactoryImplementor sessionFactory,
      int attributeNumber,
      Property property,
      boolean lazyAvailable) {
    String mappedUnsavedValue = ((KeyValue) property.getValue()).getNullValue();

    VersionValue unsavedValue =
        UnsavedValueFactory.getUnsavedVersionValue(
            mappedUnsavedValue,
            getGetter(property),
            (VersionType) property.getType(),
            getConstructor(property.getPersistentClass()));

    boolean lazy = lazyAvailable && property.isLazy();

    return new VersionProperty(
        persister,
        sessionFactory,
        attributeNumber,
        property.getName(),
        property.getValue().getType(),
        new BaselineAttributeInformation.Builder()
            .setLazy(lazy)
            .setInsertable(property.isInsertable())
            .setUpdateable(property.isUpdateable())
            .setValueGenerationStrategy(property.getValueGenerationStrategy())
            .setNullable(property.isOptional())
            .setDirtyCheckable(property.isUpdateable() && !lazy)
            .setVersionable(property.isOptimisticLocked())
            .setCascadeStyle(property.getCascadeStyle())
            .createInformation(),
        unsavedValue);
  }
  public String generateAnnColumnAnnotation(Property property) {
    StringBuffer annotations = new StringBuffer("    ");
    boolean insertable = property.isInsertable();
    boolean updatable = property.isUpdateable();
    if (property.isComposite()) {
      annotations.append("@" + importType("javax.persistence.AttributeOverrides") + "( {");
      Component component = (Component) property.getValue();
      Iterator<?> subElements = component.getPropertyIterator();
      buildRecursiveAttributeOverride(subElements, null, property, annotations);
      annotations.setLength(annotations.length() - 2);
      annotations.append(" } )");
    } else {
      if (property.getColumnSpan() == 1) {
        Selectable selectable = (Selectable) property.getColumnIterator().next();
        buildColumnAnnotation(selectable, annotations, insertable, updatable);
      } else {
        Iterator<?> columns = property.getColumnIterator();
        annotations
            .append("@")
            .append(importType("org.hibernate.annotations.Columns"))
            .append("( { ");
        while (columns.hasNext()) {
          Selectable selectable = (Selectable) columns.next();

          if (selectable.isFormula()) {
            // TODO formula in multicolumns not supported by annotations
            // annotations.append("/* TODO formula in multicolumns not supported by annotations
            // */");
          } else {
            annotations.append("\n        ");
            buildColumnAnnotation(selectable, annotations, insertable, updatable);
            annotations.append(", ");
          }
        }
        annotations.setLength(annotations.length() - 2);
        annotations.append(" } )");
      }
    }
    return annotations.toString();
  }
 private void buildRecursiveAttributeOverride(
     Iterator<?> subElements, String path, Property property, StringBuffer annotations) {
   while (subElements.hasNext()) {
     Property subProperty = (Property) subElements.next();
     if (subProperty.isComposite()) {
       if (path != null) {
         path = path + ".";
       } else {
         path = "";
       }
       path = path + subProperty.getName();
       Component component = (Component) subProperty.getValue();
       buildRecursiveAttributeOverride(
           component.getPropertyIterator(), path, subProperty, annotations);
     } else {
       Iterator<?> columns = subProperty.getColumnIterator();
       Selectable selectable = (Selectable) columns.next();
       if (selectable.isFormula()) {
         // TODO formula in multicolumns not supported by annotations
       } else {
         annotations
             .append("\n        ")
             .append("@")
             .append(importType("javax.persistence.AttributeOverride"))
             .append("(name=\"");
         if (path != null) {
           annotations.append(path).append(".");
         }
         annotations.append(subProperty.getName()).append("\"").append(", column=");
         buildColumnAnnotation(
             selectable, annotations, subProperty.isInsertable(), subProperty.isUpdateable());
         annotations.append(" ), ");
       }
     }
   }
 }
  /**
   * Generate a non-identifier (and non-version) attribute based on the given mapped property from
   * the given entity
   *
   * @param property The mapped property.
   * @param lazyAvailable Is property lazy loading currently available.
   * @return The appropriate NonIdentifierProperty definition.
   */
  public static NonIdentifierAttribute buildEntityBasedAttribute(
      EntityPersister persister,
      SessionFactoryImplementor sessionFactory,
      int attributeNumber,
      Property property,
      boolean lazyAvailable) {
    final Type type = property.getValue().getType();

    final NonIdentifierAttributeNature nature = decode(type);

    // we need to dirty check collections, since they can cause an owner
    // version number increment

    // we need to dirty check many-to-ones with not-found="ignore" in order
    // to update the cache (not the database), since in this case a null
    // entity reference can lose information

    boolean alwaysDirtyCheck =
        type.isAssociationType() && ((AssociationType) type).isAlwaysDirtyChecked();

    switch (nature) {
      case BASIC:
        {
          return new EntityBasedBasicAttribute(
              persister,
              sessionFactory,
              attributeNumber,
              property.getName(),
              type,
              new BaselineAttributeInformation.Builder()
                  .setLazy(lazyAvailable && property.isLazy())
                  .setInsertable(property.isInsertable())
                  .setUpdateable(property.isUpdateable())
                  .setValueGenerationStrategy(property.getValueGenerationStrategy())
                  .setNullable(property.isOptional())
                  .setDirtyCheckable(alwaysDirtyCheck || property.isUpdateable())
                  .setVersionable(property.isOptimisticLocked())
                  .setCascadeStyle(property.getCascadeStyle())
                  .setFetchMode(property.getValue().getFetchMode())
                  .createInformation());
        }
      case COMPOSITE:
        {
          return new EntityBasedCompositionAttribute(
              persister,
              sessionFactory,
              attributeNumber,
              property.getName(),
              (CompositeType) type,
              new BaselineAttributeInformation.Builder()
                  .setLazy(lazyAvailable && property.isLazy())
                  .setInsertable(property.isInsertable())
                  .setUpdateable(property.isUpdateable())
                  .setValueGenerationStrategy(property.getValueGenerationStrategy())
                  .setNullable(property.isOptional())
                  .setDirtyCheckable(alwaysDirtyCheck || property.isUpdateable())
                  .setVersionable(property.isOptimisticLocked())
                  .setCascadeStyle(property.getCascadeStyle())
                  .setFetchMode(property.getValue().getFetchMode())
                  .createInformation());
        }
      case ENTITY:
      case ANY:
      case COLLECTION:
        {
          return new EntityBasedAssociationAttribute(
              persister,
              sessionFactory,
              attributeNumber,
              property.getName(),
              (AssociationType) type,
              new BaselineAttributeInformation.Builder()
                  .setLazy(lazyAvailable && property.isLazy())
                  .setInsertable(property.isInsertable())
                  .setUpdateable(property.isUpdateable())
                  .setValueGenerationStrategy(property.getValueGenerationStrategy())
                  .setNullable(property.isOptional())
                  .setDirtyCheckable(alwaysDirtyCheck || property.isUpdateable())
                  .setVersionable(property.isOptimisticLocked())
                  .setCascadeStyle(property.getCascadeStyle())
                  .setFetchMode(property.getValue().getFetchMode())
                  .createInformation());
        }
      default:
        {
          throw new HibernateException("Internal error");
        }
    }
  }