| package org.apache.archiva.redback.components.modello.jpox; |
| |
| /* |
| * 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. |
| */ |
| |
| import org.apache.archiva.redback.components.modello.db.SQLReservedWords; |
| import org.apache.archiva.redback.components.modello.db.SQLReservedWords.KeywordSource; |
| import org.apache.archiva.redback.components.modello.jpox.metadata.JPoxAssociationMetadata; |
| import org.apache.archiva.redback.components.modello.jpox.metadata.JPoxClassMetadata; |
| import org.apache.archiva.redback.components.modello.jpox.metadata.JPoxFieldMetadata; |
| import org.apache.archiva.redback.components.modello.jpox.metadata.JPoxModelMetadata; |
| import org.apache.archiva.redback.components.modello.plugin.store.metadata.StoreAssociationMetadata; |
| import org.apache.archiva.redback.components.modello.plugin.store.metadata.StoreFieldMetadata; |
| import org.codehaus.modello.ModelloException; |
| import org.codehaus.modello.ModelloParameterConstants; |
| import org.codehaus.modello.model.Model; |
| import org.codehaus.modello.model.ModelAssociation; |
| import org.codehaus.modello.model.ModelClass; |
| import org.codehaus.modello.model.ModelField; |
| import org.codehaus.modello.plugin.AbstractModelloGenerator; |
| import org.codehaus.plexus.util.StringUtils; |
| import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; |
| import org.codehaus.plexus.util.xml.XMLWriter; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.OutputStreamWriter; |
| import java.io.PrintWriter; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Enumeration; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| |
| /** |
| * @author <a href="mailto:trygvis@inamo.no">Trygve Laugstøl</a> |
| * @version $Id: JPoxJdoMappingModelloGenerator.java 829 2007-03-22 14:32:42Z joakime $ |
| * @plexus.component role="org.codehaus.modello.plugin.ModelloGenerator" |
| * role-hint="jpox-jdo-mapping" |
| */ |
| public class JPoxJdoMappingModelloGenerator |
| extends AbstractModelloGenerator |
| { |
| private static final char EOL = '\n'; |
| |
| private static final String ERROR_LINE = "----------------------------------------------------------------"; |
| |
| private final static Map<String, String> PRIMITIVE_IDENTITY_MAP; |
| |
| private final static List<String> IDENTITY_TYPES; |
| |
| private final static List<String> VALUE_STRATEGY_LIST; |
| |
| /** |
| * @plexus.requirement |
| */ |
| private SQLReservedWords sqlReservedWords; |
| |
| private String valueStrategyOverride; |
| |
| private String objectIdClassOverride; |
| |
| static |
| { |
| PRIMITIVE_IDENTITY_MAP = new HashMap<>(); |
| |
| // TODO: These should be the fully qualified class names |
| PRIMITIVE_IDENTITY_MAP.put( "short", "javax.jdo.identity.ShortIdentity" ); |
| PRIMITIVE_IDENTITY_MAP.put( "Short", "javax.jdo.identity.ShortIdentity" ); |
| PRIMITIVE_IDENTITY_MAP.put( "int", "javax.jdo.identity.IntIdentity" ); |
| PRIMITIVE_IDENTITY_MAP.put( "Integer", "javax.jdo.identity.IntIdentity" ); |
| PRIMITIVE_IDENTITY_MAP.put( "long", "javax.jdo.identity.LongIdentity" ); |
| PRIMITIVE_IDENTITY_MAP.put( "Long", "javax.jdo.identity.LongIdentity" ); |
| PRIMITIVE_IDENTITY_MAP.put( "String", "javax.jdo.identity.StringIdentity" ); |
| PRIMITIVE_IDENTITY_MAP.put( "char", "javax.jdo.identity.CharIdentity" ); |
| PRIMITIVE_IDENTITY_MAP.put( "Character", "javax.jdo.identity.CharIdentity" ); |
| PRIMITIVE_IDENTITY_MAP.put( "byte", "javax.jdo.identity.ByteIdentity" ); |
| PRIMITIVE_IDENTITY_MAP.put( "Byte", "javax.jdo.identity.ByteIdentity" ); |
| |
| IDENTITY_TYPES = new ArrayList<>(); |
| IDENTITY_TYPES.add( "application" ); |
| IDENTITY_TYPES.add( "datastore" ); |
| IDENTITY_TYPES.add( "nondurable" ); |
| |
| VALUE_STRATEGY_LIST = new ArrayList<>(); |
| //VALUE_STRATEGY_LIST.add( "off" ); -- this isn't really valid. It turns it on. We use it internally to set an explicit null |
| VALUE_STRATEGY_LIST.add( "native" ); |
| VALUE_STRATEGY_LIST.add( "sequence" ); |
| VALUE_STRATEGY_LIST.add( "identity" ); |
| VALUE_STRATEGY_LIST.add( "increment" ); |
| VALUE_STRATEGY_LIST.add( "uuid-string" ); |
| VALUE_STRATEGY_LIST.add( "uuid-hex" ); |
| VALUE_STRATEGY_LIST.add( "datastore-uuid-hex" ); |
| VALUE_STRATEGY_LIST.add( "max" ); |
| VALUE_STRATEGY_LIST.add( "auid" ); |
| } |
| |
| protected void initialize( Model model, Properties parameters ) |
| throws ModelloException |
| { |
| super.initialize( model, parameters ); |
| |
| valueStrategyOverride = parameters.getProperty( "JPOX.override.value-strategy" ); |
| objectIdClassOverride = parameters.getProperty( "JPOX.override.objectid-class" ); |
| } |
| |
| public void generate( Model model, Properties properties ) |
| throws ModelloException |
| { |
| initialize( model, properties ); |
| |
| // ---------------------------------------------------------------------- |
| // Generate the JDO files |
| // ---------------------------------------------------------------------- |
| |
| try |
| { |
| String fileName = properties.getProperty( ModelloParameterConstants.FILENAME, "package.jdo" ); |
| |
| JPoxModelMetadata metadata = (JPoxModelMetadata) model.getMetadata( JPoxModelMetadata.ID ); |
| File packageJdo = null; |
| |
| if ( metadata.isMappingInPackage() ) |
| { |
| // Use package name. |
| String packageName = model.getDefaultPackageName( isPackageWithVersion(), getGeneratedVersion() ); |
| String dir = StringUtils.replace( packageName, '.', '/' ); |
| File directory = new File( getOutputDirectory(), dir ); |
| packageJdo = new File( directory, fileName ); |
| } |
| else |
| { |
| // Use the specified location. |
| File directory = getOutputDirectory(); |
| packageJdo = new File( directory, fileName ); |
| } |
| |
| File parent = packageJdo.getParentFile(); |
| |
| if ( !parent.exists() ) |
| { |
| if ( !parent.mkdirs() ) |
| { |
| throw new ModelloException( |
| "Error while creating parent directories for the file " + "'" + packageJdo.getAbsolutePath() |
| + "'." |
| ); |
| } |
| } |
| |
| generatePackageJdo( packageJdo, model ); |
| } |
| catch ( IOException e ) |
| { |
| throw new ModelloException( "Error while writing package.jdo.", e ); |
| } |
| } |
| |
| // ---------------------------------------------------------------------- |
| // |
| // ---------------------------------------------------------------------- |
| |
| private void generatePackageJdo( File file, Model model ) |
| throws IOException, ModelloException |
| { |
| try (FileOutputStream fileOutputStream = new FileOutputStream( file )) |
| { |
| try (OutputStreamWriter fileWriter = new OutputStreamWriter( fileOutputStream, "UTF-8" )) |
| { |
| |
| try (PrintWriter printWriter = new PrintWriter( fileWriter )) |
| { |
| |
| XMLWriter writer = new PrettyPrintXMLWriter( printWriter ); |
| |
| Map<String, List<ModelClass>> classes = new HashMap<>(); |
| |
| for ( Iterator<ModelClass> it = model.getClasses( getGeneratedVersion() ).iterator(); |
| it.hasNext(); ) |
| { |
| ModelClass modelClass = it.next(); |
| |
| JPoxClassMetadata jpoxMetadata = |
| JPoxClassMetadata.class.cast( modelClass.getMetadata( JPoxClassMetadata.ID ) ); |
| |
| if ( !jpoxMetadata.isEnabled() ) |
| { |
| // Skip generation of those classes that are not enabled for the jpox plugin. |
| continue; |
| } |
| |
| String packageName = modelClass.getPackageName( isPackageWithVersion(), getGeneratedVersion() ); |
| |
| List<ModelClass> list = classes.get( packageName ); |
| |
| if ( list == null ) |
| { |
| list = new ArrayList<>(); |
| } |
| |
| list.add( modelClass ); |
| |
| classes.put( packageName, list ); |
| } |
| |
| printWriter.println( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" ); |
| printWriter.println(); |
| printWriter.println( "<!DOCTYPE jdo PUBLIC" ); |
| printWriter.println( " \"-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN\"" ); |
| printWriter.println( " \"http://java.sun.com/dtd/jdo_2_0.dtd\">" ); |
| printWriter.println(); |
| |
| writer.startElement( "jdo" ); |
| |
| for ( Map.Entry<String, List<ModelClass>> entry : classes.entrySet() ) |
| { |
| |
| List<ModelClass> list = entry.getValue(); |
| |
| if ( list.size() == 0 ) |
| { |
| continue; |
| } |
| |
| String packageName = entry.getKey(); |
| |
| writer.startElement( "package" ); |
| |
| writer.addAttribute( "name", packageName ); |
| |
| for ( ModelClass modelClass : list ) |
| { |
| writeClass( writer, modelClass ); |
| } |
| |
| if ( packageName.equals( |
| model.getDefaultPackageName( isPackageWithVersion(), getGeneratedVersion() ) ) ) |
| { |
| writeModelloMetadataClass( writer ); |
| } |
| |
| writer.endElement(); // package |
| } |
| |
| writer.endElement(); // jdo |
| |
| printWriter.println(); |
| |
| } |
| } |
| } |
| } |
| |
| private void writeClass( XMLWriter writer, ModelClass modelClass ) |
| throws ModelloException |
| { |
| JPoxClassMetadata jpoxMetadata = (JPoxClassMetadata) modelClass.getMetadata( JPoxClassMetadata.ID ); |
| |
| if ( !jpoxMetadata.isEnabled() ) |
| { |
| // Skip generation of those classes that are not enabled for the jpox plugin. |
| return; |
| } |
| |
| writer.startElement( "class" ); |
| |
| writer.addAttribute( "name", modelClass.getName() ); |
| |
| ModelClass persistenceCapableSuperclass = null; |
| |
| if ( modelClass.hasSuperClass() && modelClass.isInternalSuperClass() ) |
| { |
| persistenceCapableSuperclass = getModel().getClass( modelClass.getSuperClass(), getGeneratedVersion() ); |
| } |
| |
| if ( persistenceCapableSuperclass != null ) |
| { |
| String superPackageName = |
| persistenceCapableSuperclass.getPackageName( isPackageWithVersion(), getGeneratedVersion() ); |
| |
| writer.addAttribute( "persistence-capable-superclass", |
| superPackageName + "." + persistenceCapableSuperclass.getName() ); |
| } |
| |
| writer.addAttribute( "detachable", String.valueOf( jpoxMetadata.isDetachable() ) ); |
| |
| writer.addAttribute( "table", getTableName( modelClass, jpoxMetadata ) ); |
| |
| // ---------------------------------------------------------------------- |
| // If this class has a primary key field mark make jpox manage the id |
| // as a autoincrement variable |
| // ---------------------------------------------------------------------- |
| |
| List fields = Collections.unmodifiableList( modelClass.getFields( getGeneratedVersion() ) ); |
| |
| // TODO: for now, assume that any primary key will be set in the super class |
| // While it should be possible to have abstract super classes and have the |
| // key defined in the sub class this is not implemented yet. |
| |
| boolean needInheritance = false; |
| |
| if ( persistenceCapableSuperclass == null ) |
| { |
| if ( StringUtils.isNotEmpty( jpoxMetadata.getIdentityType() ) ) |
| { |
| String identityType = jpoxMetadata.getIdentityType(); |
| if ( !IDENTITY_TYPES.contains( identityType ) ) |
| { |
| throw new ModelloException( |
| "The JDO mapping generator does not support the specified " + "class identity type '" |
| + identityType + "'. " + "Supported types: " + IDENTITY_TYPES |
| ); |
| } |
| writer.addAttribute( "identity-type", identityType ); |
| } |
| else if ( isInstantionApplicationType( modelClass ) ) |
| { |
| writer.addAttribute( "identity-type", "application" ); |
| } |
| } |
| else |
| { |
| needInheritance = true; |
| } |
| |
| if ( objectIdClassOverride != null ) |
| { |
| if ( StringUtils.isNotEmpty( objectIdClassOverride ) ) |
| { |
| writer.addAttribute( "objectid-class", jpoxMetadata.getIdentityClass() ); |
| } |
| } |
| else if ( StringUtils.isNotEmpty( jpoxMetadata.getIdentityClass() ) ) |
| { |
| // Use user provided objectId class. |
| writer.addAttribute( "objectid-class", jpoxMetadata.getIdentityClass() ); |
| } |
| else |
| { |
| // Calculate the objectId class. |
| |
| List primaryKeys = getPrimaryKeyFields( modelClass ); |
| |
| // TODO: write generation support for multi-primary-key support. |
| // would likely need to write a java class that can supply an ObjectIdentity |
| // to the jpox/jdo implementation. |
| if ( primaryKeys.size() > 1 ) |
| { |
| throw new ModelloException( |
| "The JDO mapping generator does not yet support Object Identifier generation " + "for the " |
| + primaryKeys.size() + " fields specified as <identifier> or " |
| + "with jpox.primary-key=\"true\"" |
| ); |
| } |
| |
| if ( primaryKeys.size() == 1 ) |
| { |
| ModelField modelField = (ModelField) primaryKeys.get( 0 ); |
| String objectIdClass = (String) PRIMITIVE_IDENTITY_MAP.get( modelField.getType() ); |
| |
| if ( StringUtils.isNotEmpty( objectIdClass ) ) |
| { |
| writer.addAttribute( "objectid-class", objectIdClass ); |
| } |
| } |
| } |
| |
| if ( needInheritance ) |
| { |
| writer.startElement( "inheritance" ); |
| |
| // TODO: The table strategy should be customizable |
| // http://www.jpox.org/docs/1_1/inheritance.html - in particular |
| // the strategy="subclass-table" and strategy="new-table" parts |
| |
| writer.addAttribute( "strategy", "new-table" ); |
| |
| writer.endElement(); |
| } |
| |
| // ---------------------------------------------------------------------- |
| // Write all fields |
| // ---------------------------------------------------------------------- |
| |
| for ( Iterator it = fields.iterator(); it.hasNext(); ) |
| { |
| ModelField modelField = (ModelField) it.next(); |
| |
| writeModelField( writer, modelField ); |
| } |
| |
| // Write ignored fields. |
| List ignoredFields = jpoxMetadata.getNotPersisted(); |
| if ( ignoredFields != null ) |
| { |
| Iterator it = ignoredFields.iterator(); |
| while ( it.hasNext() ) |
| { |
| String fieldName = (String) it.next(); |
| writer.startElement( "field" ); |
| writer.addAttribute( "name", fieldName ); |
| writer.addAttribute( "persistence-modifier", "none" ); |
| writer.endElement(); |
| } |
| } |
| |
| // ---------------------------------------------------------------------- |
| // Write out the "detailed" fetch group. This group will by default |
| // contain all fields in a object. The default fetch group will contain |
| // all the primitives in a class as by JDO defaults. |
| // ---------------------------------------------------------------------- |
| |
| List detailedFields = new ArrayList(); |
| |
| for ( Iterator it = fields.iterator(); it.hasNext(); ) |
| { |
| ModelField field = (ModelField) it.next(); |
| |
| if ( field.isPrimitive() ) |
| { |
| continue; |
| } |
| |
| if ( field instanceof ModelAssociation ) |
| { |
| StoreAssociationMetadata storeMetadata = getAssociationMetadata( (ModelAssociation) field ); |
| |
| if ( storeMetadata.isPart() != null && storeMetadata.isPart().booleanValue() ) |
| { |
| continue; |
| } |
| } |
| |
| detailedFields.add( field ); |
| } |
| |
| // ---------------------------------------------------------------------- |
| // Write all fetch groups |
| // ---------------------------------------------------------------------- |
| |
| // Write defaut detail fetch group |
| writeFetchGroup( writer, modelClass.getName() + "_detail", detailedFields, true ); |
| |
| // Write user fetch groups |
| Map fetchsMap = new HashMap(); |
| |
| for ( Iterator it = fields.iterator(); it.hasNext(); ) |
| { |
| ModelField field = (ModelField) it.next(); |
| |
| JPoxFieldMetadata jpoxFieldMetadata = (JPoxFieldMetadata) field.getMetadata( JPoxFieldMetadata.ID ); |
| |
| List names = jpoxFieldMetadata.getFetchGroupNames(); |
| |
| if ( names != null ) |
| { |
| for ( Iterator i = names.iterator(); i.hasNext(); ) |
| { |
| String fetchGroupName = (String) i.next(); |
| |
| List fetchList; |
| |
| if ( fetchsMap.get( fetchGroupName ) == null ) |
| { |
| fetchList = new ArrayList(); |
| } |
| else |
| { |
| fetchList = (List) fetchsMap.get( fetchGroupName ); |
| } |
| |
| fetchList.add( field ); |
| |
| fetchsMap.put( fetchGroupName, fetchList ); |
| } |
| } |
| } |
| |
| for ( Iterator it = fetchsMap.keySet().iterator(); it.hasNext(); ) |
| { |
| String fetchName = (String) it.next(); |
| |
| writeFetchGroup( writer, fetchName, (List) fetchsMap.get( fetchName ), false ); |
| } |
| |
| writer.endElement(); // class |
| } |
| |
| /** |
| * Utility method to obtain the table name from the {@link ModelClass} or {@link JPoxClassMetadata} taking into |
| * account the possibility of prefixes in use at the {@link JPoxModelMetadata} level. |
| * |
| * @param modelClass the model class to get the class.name from. |
| * @param classMetadata the class metadata to get the class-metadata.table name from. |
| * @return the table name (with possible prefix applied) |
| * @throws ModelloException if there was a problem with the table name violating a sql reserved word. |
| */ |
| private String getTableName( ModelClass modelClass, JPoxClassMetadata classMetadata ) |
| throws ModelloException |
| { |
| JPoxModelMetadata modelMetadata = (JPoxModelMetadata) modelClass.getModel().getMetadata( JPoxModelMetadata.ID ); |
| |
| boolean hasPrefix = StringUtils.isNotEmpty( modelMetadata.getTablePrefix() ); |
| boolean hasAlternateName = StringUtils.isNotEmpty( classMetadata.getTable() ); |
| |
| String prefix = ""; |
| |
| if ( hasPrefix ) |
| { |
| prefix = modelMetadata.getTablePrefix().trim(); |
| } |
| |
| String tableName = null; |
| |
| if ( hasAlternateName ) |
| { |
| tableName = prefix + classMetadata.getTable(); |
| } |
| else |
| { |
| tableName = prefix + modelClass.getName(); |
| } |
| |
| if ( sqlReservedWords.isKeyword( tableName ) ) |
| { |
| StringBuffer emsg = new StringBuffer(); |
| |
| /* ---------------------------------------------------------------- |
| * SQL Reserved Word Violation: 'ROLES' |
| * Context: TABLE NAME |
| */ |
| emsg.append( EOL ).append( ERROR_LINE ).append( EOL ); |
| emsg.append( " SQL Reserved Word Violation: " ).append( tableName ).append( EOL ); |
| emsg.append( " Context: TABLE NAME" ).append( EOL ); |
| emsg.append( " " ).append( EOL ); |
| |
| /* In Model: |
| * <model jpox.table-prefix=""> |
| * <class jpox.table=""> |
| * <name>JdoRole</name> |
| * </class> |
| * </model> |
| */ |
| emsg.append( " In Model:" ).append( EOL ); |
| emsg.append( " <model" ); |
| if ( hasPrefix ) |
| { |
| emsg.append( " jpox.table-prefix=\"" ).append( modelMetadata.getTablePrefix() ).append( "\"" ); |
| } |
| emsg.append( ">" ).append( EOL ); |
| emsg.append( " <class" ); |
| if ( hasAlternateName ) |
| { |
| emsg.append( " jpox.table=\"" ).append( classMetadata.getTable() ).append( "\"" ); |
| } |
| emsg.append( ">" ).append( EOL ); |
| emsg.append( " <name>" ).append( modelClass.getName() ).append( "</name>" ).append( EOL ); |
| emsg.append( " </class>" ).append( EOL ); |
| emsg.append( " </model>" ).append( EOL ); |
| emsg.append( " " ).append( EOL ); |
| |
| /* Violation Source(s): Oracle (WARNING) |
| * SQL 99 (ERROR) |
| * |
| * Severity: ERROR - You must change this name for maximum |
| * compatibility amoungst JDBC SQL Servers. |
| * |
| * Severity: WARNING - You are encouraged to change this name |
| * for maximum compatibility amoungst JDBC SQL Servers. |
| */ |
| boolean hasError = appendKeywordSourceViolations( tableName, emsg ); |
| |
| /* Suggestions: 1) Use a different prefix in |
| * <model jpox.table-prefix="DIFFERENT_"> |
| * 2) Use a different alternate table name using |
| * <class jpox.table="DIFFERENT"> |
| * 3) Use a different class name in |
| * <class> |
| * <name>DIFFERENT</name> |
| * </class> |
| * ---------------------------------------------------------------- |
| */ |
| emsg.append( " Suggestions: 1) Use a different prefix in" ).append( EOL ); |
| emsg.append( " <model jpox.table-prefix=\"DIFFERENT_\">" ).append( EOL ); |
| emsg.append( " 2) Use a different alternate table name using" ).append( EOL ); |
| emsg.append( " <class jpox.table=\"DIFFERENT\">" ).append( EOL ); |
| emsg.append( " 3) Use a different class name in" ).append( EOL ); |
| emsg.append( " <class>" ).append( EOL ); |
| emsg.append( " <name>DIFFERENT</name>" ).append( EOL ); |
| emsg.append( " </class>" ).append( EOL ); |
| |
| emsg.append( ERROR_LINE ); |
| |
| // Determine possible exception. |
| if ( hasError || modelMetadata.getReservedWordStrictness().equals( JPoxModelMetadata.WARNING ) ) |
| { |
| throw new ModelloException( emsg.toString() ); |
| } |
| |
| // No exception. use it. But log it. |
| getLogger().warn( emsg.toString() ); |
| } |
| |
| return tableName; |
| } |
| |
| /** |
| * Support method for the {@link #getTableName(ModelClass, JPoxClassMetadata)}, |
| * {@link #getColumnName(ModelField, JPoxFieldMetadata)}, and |
| * {@link #getJoinTableName(ModelField, JPoxFieldMetadata)} reserved word tests. |
| * |
| * @param word the word in violation. |
| * @param emsg the string buffer to append to. |
| * @return if this word has any ERROR severity level violations. |
| */ |
| private boolean appendKeywordSourceViolations( String word, StringBuffer emsg ) |
| { |
| List sources = sqlReservedWords.getKeywordSourceList( word ); |
| boolean hasError = false; |
| emsg.append( " Violation Source(s): " ); |
| for ( Iterator it = sources.iterator(); it.hasNext(); ) |
| { |
| KeywordSource source = (KeywordSource) it.next(); |
| emsg.append( source.getName() ).append( " (" ).append( source.getSeverity() ).append( ")" ); |
| emsg.append( EOL ); |
| |
| if ( source.getSeverity().equalsIgnoreCase( "ERROR" ) ) |
| { |
| hasError = true; |
| } |
| |
| if ( it.hasNext() ) |
| { |
| emsg.append( " " ); |
| } |
| } |
| emsg.append( " " ).append( EOL ); |
| |
| emsg.append( " Severity: " ); |
| if ( hasError ) |
| { |
| emsg.append( "ERROR - You must change this name for the maximum" ).append( EOL ); |
| emsg.append( " compatibility amoungst JDBC SQL Servers." ).append( EOL ); |
| } |
| else |
| { |
| emsg.append( "WARNING - You are encouraged to change this name" ).append( EOL ); |
| emsg.append( " for maximum compatibility amoungst JDBC SQL Servers." ).append( EOL ); |
| } |
| emsg.append( " " ).append( EOL ); |
| |
| return hasError; |
| } |
| |
| private void writeModelloMetadataClass( XMLWriter writer ) |
| throws ModelloException |
| { |
| writer.startElement( "class" ); |
| |
| writer.addAttribute( "name", getModel().getName() + "ModelloMetadata" ); |
| |
| writer.addAttribute( "detachable", String.valueOf( true ) ); |
| |
| writer.startElement( "field" ); |
| |
| writer.addAttribute( "name", "modelVersion" ); |
| writer.addAttribute( "null-value", "default" ); |
| |
| writer.startElement( "column" ); |
| |
| writer.addAttribute( "default-value", getGeneratedVersion().toString() ); |
| |
| writer.endElement(); // column |
| |
| writer.endElement(); // field |
| |
| writer.endElement(); // class |
| } |
| |
| private void writeFetchGroup( XMLWriter writer, String fetchGroupName, List fields, boolean onlyIfIsStashPart ) |
| { |
| if ( !fields.isEmpty() ) |
| { |
| writer.startElement( "fetch-group" ); |
| |
| writer.addAttribute( "name", fetchGroupName ); |
| |
| for ( Iterator it = fields.iterator(); it.hasNext(); ) |
| { |
| ModelField field = (ModelField) it.next(); |
| |
| if ( onlyIfIsStashPart && ( field instanceof ModelAssociation ) ) |
| { |
| StoreAssociationMetadata storeMetadata = getAssociationMetadata( (ModelAssociation) field ); |
| |
| if ( storeMetadata.isPart() != null && storeMetadata.isPart().booleanValue() ) |
| { |
| continue; |
| } |
| } |
| |
| writer.startElement( "field" ); |
| |
| writer.addAttribute( "name", field.getName() ); |
| |
| writer.endElement(); |
| } |
| |
| writer.endElement(); // fetch-group |
| } |
| } |
| |
| private void writeModelField( XMLWriter writer, ModelField modelField ) |
| throws ModelloException |
| { |
| writer.startElement( "field" ); |
| |
| StoreFieldMetadata storeMetadata = (StoreFieldMetadata) modelField.getMetadata( StoreFieldMetadata.ID ); |
| |
| JPoxFieldMetadata jpoxMetadata = (JPoxFieldMetadata) modelField.getMetadata( JPoxFieldMetadata.ID ); |
| |
| writer.addAttribute( "name", modelField.getName() ); |
| |
| if ( !storeMetadata.isStorable() ) |
| { |
| writer.addAttribute( "persistence-modifier", "none" ); |
| } |
| else if ( StringUtils.isNotEmpty( jpoxMetadata.getPersistenceModifier() ) ) |
| { |
| writer.addAttribute( "persistence-modifier", jpoxMetadata.getPersistenceModifier() ); |
| } |
| |
| if ( modelField.isRequired() ) |
| { |
| writer.addAttribute( "null-value", "exception" ); |
| } |
| else if ( jpoxMetadata.getNullValue() != null ) |
| { |
| writer.addAttribute( "null-value", jpoxMetadata.getNullValue() ); |
| } |
| |
| String columnName = getColumnName( modelField, jpoxMetadata ); |
| |
| if ( StringUtils.isNotEmpty( jpoxMetadata.getJoinTableName() ) ) |
| { |
| writer.addAttribute( "table", getJoinTableName( modelField, jpoxMetadata ) ); |
| } |
| |
| if ( jpoxMetadata.isPrimaryKey() ) |
| { |
| writer.addAttribute( "primary-key", "true" ); |
| |
| // value-strategy is only useful when you have a primary-key defined for the field. |
| if ( StringUtils.isNotEmpty( valueStrategyOverride ) ) |
| { |
| writeValueStrategy( valueStrategyOverride, writer ); |
| } |
| else if ( StringUtils.isNotEmpty( jpoxMetadata.getValueStrategy() ) ) |
| { |
| writeValueStrategy( jpoxMetadata.getValueStrategy(), writer ); |
| } |
| } |
| |
| if ( StringUtils.isNotEmpty( jpoxMetadata.getIndexed() ) ) |
| { |
| writer.addAttribute( "indexed", jpoxMetadata.getIndexed() ); |
| } |
| |
| if ( StringUtils.isNotEmpty( jpoxMetadata.getMappedBy() ) ) |
| { |
| writer.addAttribute( "mapped-by", jpoxMetadata.getMappedBy() ); |
| } |
| |
| if ( modelField instanceof ModelAssociation ) |
| { |
| writeAssociation( writer, (ModelAssociation) modelField ); |
| } |
| else |
| { |
| if ( modelField.isPrimitiveArray() ) |
| { |
| writer.startElement( "array" ); |
| writer.endElement(); |
| } |
| |
| // Work out potential <column> subelement |
| |
| // Store potential column properties. |
| Properties columnProps = new Properties(); |
| |
| if ( !StringUtils.equalsIgnoreCase( columnName, modelField.getName() ) ) |
| { |
| columnProps.setProperty( "name", columnName ); |
| } |
| |
| if ( storeMetadata.getMaxSize() > 0 ) |
| { |
| columnProps.setProperty( "length", String.valueOf( storeMetadata.getMaxSize() ) ); |
| } |
| |
| if ( StringUtils.equals( jpoxMetadata.getNullValue(), "default" ) ) |
| { |
| columnProps.setProperty( "default-value", modelField.getDefaultValue() ); |
| } |
| |
| // Now write the column sub element (if it has properties) |
| if ( !columnProps.isEmpty() ) |
| { |
| writer.startElement( "column" ); |
| |
| for ( Enumeration en = columnProps.propertyNames(); en.hasMoreElements(); ) |
| { |
| String attributeName = (String) en.nextElement(); |
| String attributeValue = columnProps.getProperty( attributeName ); |
| writer.addAttribute( attributeName, attributeValue ); |
| |
| } |
| writer.endElement(); |
| } |
| |
| // Work out potential <unique> subelement. |
| if ( jpoxMetadata.isUnique() ) |
| { |
| writer.startElement( "unique" ); |
| writer.addAttribute( "name", columnName.toUpperCase() + "_UNIQUE_CONSTRAINT" ); |
| writer.endElement(); |
| } |
| |
| // Work out potential <foreign-key> subelement |
| if ( jpoxMetadata.isForeignKey() ) |
| { |
| writer.startElement( "foreign-key" ); |
| writer.addAttribute( "name", columnName.toUpperCase() + "_FK" ); |
| |
| if ( StringUtils.isNotEmpty( jpoxMetadata.getForeignKeyDeferred() ) ) |
| { |
| writer.addAttribute( "deferred", jpoxMetadata.getForeignKeyDeferred() ); |
| } |
| |
| if ( StringUtils.isNotEmpty( jpoxMetadata.getForeignKeyDeleteAction() ) ) |
| { |
| writer.addAttribute( "delete-action", jpoxMetadata.getForeignKeyDeleteAction() ); |
| } |
| |
| if ( StringUtils.isNotEmpty( jpoxMetadata.getForeignKeyUpdateAction() ) ) |
| { |
| writer.addAttribute( "update-action", jpoxMetadata.getForeignKeyUpdateAction() ); |
| } |
| writer.endElement(); |
| } |
| } |
| |
| writer.endElement(); // field |
| } |
| |
| /** |
| * Utility method to obtain the join table name from the {@link JPoxFieldMetadata} taking into |
| * account the possibility of prefixes in use at the {@link JPoxModelMetadata} level. |
| * |
| * @param modelField the model field to get the field.name from. |
| * @param fieldMetadata the field metadata to get the field-metadata.join-table name from. |
| * @return the join table name (with possible prefix applied) |
| * @throws ModelloException if there was a problem with the table name violating a sql reserved word. |
| */ |
| private String getJoinTableName( ModelField modelField, JPoxFieldMetadata fieldMetadata ) |
| throws ModelloException |
| { |
| ModelClass modelClass = modelField.getModelClass(); |
| JPoxModelMetadata modelMetadata = (JPoxModelMetadata) modelClass.getModel().getMetadata( JPoxModelMetadata.ID ); |
| |
| boolean hasPrefix = StringUtils.isNotEmpty( modelMetadata.getTablePrefix() ); |
| |
| String prefix = ""; |
| |
| if ( hasPrefix ) |
| { |
| prefix = modelMetadata.getTablePrefix().trim(); |
| } |
| |
| String joinTableName = prefix + fieldMetadata.getJoinTableName(); |
| ; |
| |
| if ( sqlReservedWords.isKeyword( joinTableName ) ) |
| { |
| StringBuffer emsg = new StringBuffer(); |
| |
| /* ---------------------------------------------------------------- |
| * SQL Reserved Word Violation: 'ROLES' |
| * Context: TABLE NAME |
| */ |
| emsg.append( EOL ).append( ERROR_LINE ).append( EOL ); |
| emsg.append( " SQL Reserved Word Violation: " ).append( joinTableName ).append( EOL ); |
| emsg.append( " Context: JOIN TABLE NAME" ).append( EOL ); |
| emsg.append( " " ).append( EOL ); |
| |
| /* In Model: |
| * <model jpox.table-prefix=""> |
| * <class jpox.table=""> |
| * <name>JdoRole</name> |
| * <fields> |
| * <field jpox.join-table="Foo"> |
| * <name>Operation</name> |
| * </field> |
| * </fields> |
| * </class> |
| * </model> |
| */ |
| emsg.append( " In Model:" ).append( EOL ); |
| emsg.append( " <model" ); |
| if ( hasPrefix ) |
| { |
| emsg.append( " jpox.table-prefix=\"" ).append( modelMetadata.getTablePrefix() ).append( "\"" ); |
| } |
| emsg.append( ">" ).append( EOL ); |
| emsg.append( " <class>" ).append( EOL ); |
| emsg.append( " <name>" ).append( modelClass.getName() ).append( "</name>" ).append( EOL ); |
| emsg.append( " <fields>" ).append( EOL ); |
| emsg.append( " <field jpox.join-table=\"" ).append( fieldMetadata.getJoinTableName() ); |
| emsg.append( "\">" ).append( EOL ); |
| emsg.append( " <name>" ).append( modelField.getName() ).append( "</name>" ).append( EOL ); |
| emsg.append( " <field>" ).append( EOL ); |
| emsg.append( " </fields>" ).append( EOL ); |
| emsg.append( " </class>" ).append( EOL ); |
| emsg.append( " </model>" ).append( EOL ); |
| emsg.append( " " ).append( EOL ); |
| |
| /* Violation Source(s): Oracle (WARNING) |
| * SQL 99 (ERROR) |
| * |
| * Severity: ERROR - You must change this name for maximum |
| * compatibility amoungst JDBC SQL Servers. |
| * |
| * Severity: WARNING - You are encouraged to change this name |
| * for maximum compatibility amoungst JDBC SQL Servers. |
| */ |
| boolean hasError = appendKeywordSourceViolations( joinTableName, emsg ); |
| |
| /* Suggestions: 1) Use a different table prefix in |
| * <model jpox.table-prefix="DIFFERENT_"> |
| * 2) Use a different join table name using |
| * <field jpox.join-table="DIFFERENT"> |
| * ---------------------------------------------------------------- |
| */ |
| emsg.append( " Suggestions: 1) Use a different table prefix in" ).append( EOL ); |
| emsg.append( " <model jpox.table-prefix=\"DIFFERENT_\">" ).append( EOL ); |
| emsg.append( " 2) Use a different join table name using" ).append( EOL ); |
| emsg.append( " <field jpox.join-table=\"DIFFERENT\">" ).append( EOL ); |
| |
| emsg.append( ERROR_LINE ); |
| |
| // Determine possible exception. |
| if ( hasError || modelMetadata.getReservedWordStrictness().equals( JPoxModelMetadata.WARNING ) ) |
| { |
| throw new ModelloException( emsg.toString() ); |
| } |
| |
| // No exception. use it. But log it. |
| getLogger().warn( emsg.toString() ); |
| } |
| |
| return joinTableName; |
| } |
| |
| /** |
| * Utility method to obtain the column name from the {@link ModelField} or {@link JPoxFieldMetadata} taking into |
| * account the possibility of prefixes in use at the {@link JPoxModelMetadata} or {@link JPoxClassMetadata} level. |
| * |
| * @param modelField the model field to get the field.name from. |
| * @param fieldMetadata the field metadata to get the field-metadata.column name from. |
| * @return the column name (with possible prefix applied) |
| * @throws ModelloException if there was a problem with the column name violating a sql reserved word. |
| */ |
| private String getColumnName( ModelField modelField, JPoxFieldMetadata fieldMetadata ) |
| throws ModelloException |
| { |
| boolean hasClassPrefix = false; |
| boolean hasModelPrefix = false; |
| boolean hasAlternateName = false; |
| |
| ModelClass modelClass = modelField.getModelClass(); |
| JPoxClassMetadata classMetadata = (JPoxClassMetadata) modelClass.getMetadata( JPoxClassMetadata.ID ); |
| JPoxModelMetadata modelMetadata = (JPoxModelMetadata) modelClass.getModel().getMetadata( JPoxModelMetadata.ID ); |
| |
| String prefix = ""; |
| |
| if ( StringUtils.isNotEmpty( modelMetadata.getColumnPrefix() ) ) |
| { |
| prefix = modelMetadata.getColumnPrefix().trim(); |
| hasModelPrefix = true; |
| } |
| |
| if ( StringUtils.isNotEmpty( classMetadata.getColumnPrefix() ) ) |
| { |
| prefix = classMetadata.getColumnPrefix(); |
| hasClassPrefix = true; |
| } |
| |
| String columnName = ""; |
| |
| if ( StringUtils.isNotEmpty( fieldMetadata.getColumnName() ) ) |
| { |
| columnName = prefix + fieldMetadata.getColumnName(); |
| hasAlternateName = true; |
| } |
| else |
| { |
| columnName = prefix + modelField.getName(); |
| } |
| |
| if ( sqlReservedWords.isKeyword( columnName ) ) |
| { |
| StringBuffer emsg = new StringBuffer(); |
| |
| /* ---------------------------------------------------------------- |
| * SQL Reserved Word Violation: 'ROLES' |
| * Context: TABLE NAME |
| */ |
| emsg.append( EOL ).append( ERROR_LINE ).append( EOL ); |
| emsg.append( " SQL Reserved Word Violation: " ).append( columnName ).append( EOL ); |
| emsg.append( " Context: COLUMN NAME" ).append( EOL ); |
| emsg.append( " " ).append( EOL ); |
| |
| /* In Model: |
| * <model jpox.column-prefix=""> |
| * <class jpox.column-prefix=""> |
| * <name>JdoRole</name> |
| * <fields> |
| * <field jpox.column=""> |
| * <name>operation</name> |
| * </field> |
| * </fields> |
| * </class> |
| * </model> |
| */ |
| emsg.append( " In Model:" ).append( EOL ); |
| emsg.append( " <model" ); |
| if ( hasModelPrefix ) |
| { |
| emsg.append( " jpox.column-prefix=\"" ).append( modelMetadata.getColumnPrefix() ).append( "\"" ); |
| } |
| emsg.append( ">" ).append( EOL ); |
| emsg.append( " <class" ); |
| if ( hasClassPrefix ) |
| { |
| emsg.append( " jpox.column-prefix=\"" ).append( classMetadata.getColumnPrefix() ).append( "\"" ); |
| } |
| emsg.append( ">" ).append( EOL ); |
| emsg.append( " <name>" ).append( modelClass.getName() ).append( "</name>" ).append( EOL ); |
| emsg.append( " <fields>" ).append( EOL ); |
| emsg.append( " <field" ); |
| if ( hasAlternateName ) |
| { |
| emsg.append( " jpox.column=\"" ).append( fieldMetadata.getColumnName() ).append( "\"" ); |
| } |
| emsg.append( ">" ).append( EOL ); |
| emsg.append( " <name>" ).append( modelField.getName() ).append( "</name>" ).append( EOL ); |
| emsg.append( " <field>" ).append( EOL ); |
| emsg.append( " </fields>" ).append( EOL ); |
| emsg.append( " </class>" ).append( EOL ); |
| emsg.append( " </model>" ).append( EOL ); |
| emsg.append( " " ).append( EOL ); |
| |
| /* Violation Source(s): Oracle (WARNING) |
| * SQL 99 (ERROR) |
| * |
| * Severity: ERROR - You must change this name for maximum |
| * compatibility amoungst JDBC SQL Servers. |
| * |
| * Severity: WARNING - You are encouraged to change this name |
| * for maximum compatibility amoungst JDBC SQL Servers. |
| */ |
| boolean hasError = appendKeywordSourceViolations( columnName, emsg ); |
| |
| /* Suggestions: 1) Use a different model column prefix in |
| * <model jpox.column-prefix="DIFFERENT_"> |
| * 2) Use a different class column prefix in |
| * <class jpox.column-prefix="DIFFERENT_"> |
| * 3) Use a different alternate column name using |
| * <field jpox.column="DIFFERENT"> |
| * 4) Use a different field name in |
| * <class> |
| * <name>Foo</name> |
| * <fields> |
| * <field> |
| * <name>DIFFERENT</name> |
| * </field> |
| * </fields> |
| * </class> |
| * ---------------------------------------------------------------- |
| */ |
| emsg.append( " Suggestions: 1) Use a different model column prefix in" ).append( EOL ); |
| emsg.append( " <model jpox.column-prefix=\"DIFFERENT_\">" ).append( EOL ); |
| emsg.append( " 2) Use a different class column prefix in" ).append( EOL ); |
| emsg.append( " <class jpox.column-prefix=\"DIFFERENT_\">" ).append( EOL ); |
| emsg.append( " 3) Use a different alternate column name using" ).append( EOL ); |
| emsg.append( " <field jpox.column=\"DIFFERENT\">" ).append( EOL ); |
| emsg.append( " 4) Use a different field name in" ).append( EOL ); |
| emsg.append( " <class>" ).append( EOL ); |
| emsg.append( " <name>" ).append( modelClass.getName() ).append( "</name>" ).append( |
| EOL ); |
| emsg.append( " <fields>" ).append( EOL ); |
| emsg.append( " <field>" ).append( EOL ); |
| emsg.append( " <name>DIFFERENT</name>" ).append( EOL ); |
| emsg.append( " <field>" ).append( EOL ); |
| emsg.append( " </fields>" ).append( EOL ); |
| emsg.append( " </class>" ).append( EOL ); |
| |
| emsg.append( ERROR_LINE ); |
| |
| // Determine possible exception. |
| if ( hasError || modelMetadata.getReservedWordStrictness().equals( JPoxModelMetadata.WARNING ) ) |
| { |
| throw new ModelloException( emsg.toString() ); |
| } |
| |
| // No exception. use it. But log it. |
| getLogger().warn( emsg.toString() ); |
| } |
| |
| return columnName; |
| } |
| |
| private static void writeValueStrategy( String valueStrategy, XMLWriter writer ) |
| throws ModelloException |
| { |
| if ( !"off".equals( valueStrategy ) ) |
| { |
| if ( !VALUE_STRATEGY_LIST.contains( valueStrategy ) ) |
| { |
| throw new ModelloException( |
| "The JDO mapping generator does not support the specified " + "value-strategy '" + valueStrategy |
| + "'. " + "Supported types: " + VALUE_STRATEGY_LIST |
| ); |
| } |
| writer.addAttribute( "value-strategy", valueStrategy ); |
| } |
| } |
| |
| private void writeAssociation( XMLWriter writer, ModelAssociation association ) |
| { |
| StoreAssociationMetadata am = |
| (StoreAssociationMetadata) association.getAssociationMetadata( StoreAssociationMetadata.ID ); |
| |
| JPoxAssociationMetadata jpoxMetadata = |
| (JPoxAssociationMetadata) association.getAssociationMetadata( JPoxAssociationMetadata.ID ); |
| |
| if ( am.isPart() != null ) |
| { |
| // This gets added onto the <field> element |
| writer.addAttribute( "default-fetch-group", am.isPart().toString() ); |
| } |
| |
| if ( association.getType().equals( "java.util.List" ) || association.getType().equals( "java.util.Set" ) ) |
| { |
| // Start <collection> element |
| writer.startElement( "collection" ); |
| |
| if ( association.getTo().equals( "String" ) ) |
| { |
| writer.addAttribute( "element-type", "java.lang.String" ); |
| } |
| else |
| { |
| writer.addAttribute( "element-type", association.getTo() ); |
| } |
| |
| if ( jpoxMetadata.isDependent() ) |
| { |
| writer.addAttribute( "dependent-element", "true" ); |
| } |
| else |
| { |
| writer.addAttribute( "dependent-element", "false" ); |
| } |
| |
| // End <collection> element |
| writer.endElement(); |
| |
| if ( jpoxMetadata.isJoin() ) |
| { |
| writer.startElement( "join" ); |
| |
| writer.endElement(); |
| } |
| } |
| else if ( association.getType().equals( "java.util.Map" ) ) |
| { |
| writer.startElement( "map" ); |
| |
| writer.addAttribute( "key-type", am.getKeyType() ); |
| |
| if ( association.getTo().equals( "String" ) ) |
| { |
| writer.addAttribute( "value-type", "java.lang.String" ); |
| } |
| else |
| { |
| writer.addAttribute( "value-type", association.getTo() ); |
| } |
| |
| if ( jpoxMetadata.isDependent() ) |
| { |
| writer.addAttribute( "dependent-key", "true" ); |
| |
| writer.addAttribute( "dependent-value", "true" ); |
| } |
| else |
| { |
| writer.addAttribute( "dependent-key", "false" ); |
| |
| writer.addAttribute( "dependent-value", "false" ); |
| } |
| |
| writer.endElement(); |
| |
| if ( jpoxMetadata.isJoin() ) |
| { |
| writer.startElement( "join" ); |
| |
| writer.endElement(); |
| } |
| } |
| else if ( association.getType().equals( "java.util.Properties" ) ) |
| { |
| writer.addAttribute( "embedded", "false" ); |
| |
| writer.startElement( "map" ); |
| |
| writer.addAttribute( "key-type", "java.lang.String" ); |
| |
| writer.addAttribute( "value-type", "java.lang.String" ); |
| |
| writer.addAttribute( "embedded-key", "true" ); |
| |
| writer.addAttribute( "embedded-value", "true" ); |
| |
| writer.addAttribute( "dependent-key", "true" ); |
| |
| writer.addAttribute( "dependent-value", "true" ); |
| |
| writer.endElement(); |
| |
| if ( jpoxMetadata.isJoin() ) |
| { |
| writer.startElement( "join" ); |
| |
| writer.endElement(); |
| } |
| } |
| else |
| // One association |
| { |
| if ( jpoxMetadata.isDependent() ) |
| { |
| writer.addAttribute( "dependent", "true" ); |
| } |
| } |
| } |
| |
| private boolean isInstantionApplicationType( ModelClass modelClass ) |
| { |
| List identifierFields = modelClass.getIdentifierFields( getGeneratedVersion() ); |
| |
| return identifierFields.size() > 0; |
| } |
| |
| private List getPrimaryKeyFields( ModelClass modelClass ) |
| throws ModelloException |
| { |
| List primaryKeys = new ArrayList(); |
| List fields = modelClass.getFields( getGeneratedVersion() ); |
| JPoxClassMetadata jpoxClassMetadata = (JPoxClassMetadata) modelClass.getMetadata( JPoxClassMetadata.ID ); |
| |
| for ( Iterator it = fields.iterator(); it.hasNext(); ) |
| { |
| ModelField modelField = (ModelField) it.next(); |
| JPoxFieldMetadata jpoxFieldMetadata = (JPoxFieldMetadata) modelField.getMetadata( JPoxFieldMetadata.ID ); |
| |
| if ( jpoxClassMetadata.useIdentifiersAsPrimaryKey() ) |
| { |
| if ( modelField.isIdentifier() ) |
| { |
| assertSupportedIdentityPrimitive( modelField ); |
| primaryKeys.add( modelField ); |
| } |
| } |
| else |
| { |
| if ( jpoxFieldMetadata.isPrimaryKey() ) |
| { |
| assertSupportedIdentityPrimitive( modelField ); |
| primaryKeys.add( modelField ); |
| } |
| } |
| } |
| |
| return primaryKeys; |
| } |
| |
| private void assertSupportedIdentityPrimitive( ModelField modelField ) |
| throws ModelloException |
| { |
| if ( !PRIMITIVE_IDENTITY_MAP.containsKey( modelField.getType() ) ) |
| { |
| throw new ModelloException( |
| "The JDO mapping generator does not support the specified " + "field type '" + modelField.getType() |
| + "'. " + "Supported types: " + PRIMITIVE_IDENTITY_MAP.keySet() |
| ); |
| } |
| } |
| |
| private StoreAssociationMetadata getAssociationMetadata( ModelAssociation association ) |
| { |
| return (StoreAssociationMetadata) association.getAssociationMetadata( StoreAssociationMetadata.ID ); |
| } |
| } |