OPENJPA-143

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@566788 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Michael Dick 2007-08-16 17:59:57 +00:00
parent 8d1dacad82
commit 6cd259f310
16 changed files with 568 additions and 36 deletions

View File

@ -33,6 +33,7 @@ import org.apache.openjpa.jdbc.sql.Select;
import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.meta.MetaDataContext;
import org.apache.openjpa.meta.MetaDataModes;
import org.apache.openjpa.meta.MetaDataRepository;
@ -65,6 +66,8 @@ public class Discriminator
private boolean _subsLoaded = false;
private Object _value = null;
private int _javaType = -1;
/**
* Constructor. Supply owning mapping.
*/
@ -413,4 +416,21 @@ public class Discriminator
public String toString() {
return _mapping + "<discriminator>";
}
public void setJavaType(int javaType) {
_javaType = javaType;
}
public int getJavaType() {
if (_javaType == -1) {
ClassMapping superMapping = _mapping.getPCSuperclassMapping();
if (superMapping != null &&
superMapping.getDiscriminator() != null) {
_javaType = superMapping.getDiscriminator().getJavaType();
}
}
return _javaType;
}
}

View File

@ -20,6 +20,7 @@ package org.apache.openjpa.jdbc.meta;
import java.lang.reflect.Modifier;
import org.apache.commons.lang.StringUtils;
import org.apache.openjpa.jdbc.meta.strats.NoneDiscriminatorStrategy;
import org.apache.openjpa.jdbc.meta.strats.SuperclassDiscriminatorStrategy;
import org.apache.openjpa.jdbc.meta.strats.ValueMapDiscriminatorStrategy;
@ -28,6 +29,7 @@ import org.apache.openjpa.jdbc.schema.Index;
import org.apache.openjpa.jdbc.schema.SchemaGroup;
import org.apache.openjpa.jdbc.schema.Table;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.util.MetaDataException;
/**
@ -66,29 +68,21 @@ public class DiscriminatorMappingInfo
public Object getValue(Discriminator discrim, boolean adapt) {
if (discrim.getValue() != null)
return discrim.getValue();
if (_value == null)
if (StringUtils.isEmpty(_value)) {
return discrim.getMappingRepository().getMappingDefaults().
getDiscriminatorValue(discrim, adapt);
if (_value.length() > 0 && (_value.charAt(0) == '-'
|| Character.isDigit(_value.charAt(0)))) {
try {
if (_value.indexOf('.') == -1)
return new Integer(_value);
return new Double(_value);
} catch (RuntimeException re) {
throw new MetaDataException(_loc.get("bad-discrim-value",
discrim.getClassMapping(), _value));
}
}
if ("null".equalsIgnoreCase(_value))
return Discriminator.NULL;
// strip quotes
if (_value.length() > 0 && _value.charAt(0) == '\'')
return _value.substring(1, _value.length() - 1);
switch(discrim.getJavaType()) {
case JavaTypes.INT:
return Integer.valueOf(_value);
case JavaTypes.CHAR:
return Character.valueOf(_value.charAt(_value.indexOf('\'')+1));
case JavaTypes.STRING:
default:
return _value;
}
}
/**
* Return the columns set for this discriminator, based on the given

View File

@ -455,14 +455,47 @@ public class MappingDefaultsImpl
return null;
}
/**
* Provides a default value for the given Discriminator.
*
* <P>
* The type of the object returned relies on the javaType field being set on
* the Discriminator which is provided.
* <TABLE border="2">
* <TH>JavaType
* <TH>Default value
* <TBODY>
* <TR><TD>{@link JavaTypes.INT}<TD> The hashcode of the entity name</TR>
* <TR><TD>{@link JavaTypes.CHAR}<TD>The first character of the entity name
* </TR>
* <TR><TD>{@link JavaTypes.STRING}<TD>The entity name</TR>
* </TBODY>
* </TABLE>
*
* @param disc The discriminator that needs a default value
* @param adapt
*
* @return A new object containing the generated Discriminator value.
*/
public Object getDiscriminatorValue(Discriminator disc, boolean adapt) {
if (!adapt && !defaultMissingInfo())
return null;
// WARNING: CHANGING THIS WILL INVALIDATE EXISTING DATA IF DEFAULTING
// MISSING MAPPING INFO
return Strings.getClassName(disc.getClassMapping().
getDescribedType());
String alias = Strings.getClassName(disc.getClassMapping()
.getTypeAlias());
switch (disc.getJavaType()) {
case JavaTypes.INT:
return new Integer(alias.hashCode());
case JavaTypes.CHAR:
return new Character(alias.charAt(0));
case JavaTypes.STRING:
default:
return alias;
}
}
public String getTableName(ClassMapping cls, Schema schema) {

View File

@ -20,6 +20,7 @@ package org.apache.openjpa.persistence.jdbc;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Modifier;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
@ -57,6 +58,7 @@ import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.kernel.EagerFetchModes;
import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.meta.ClassMappingInfo;
import org.apache.openjpa.jdbc.meta.Discriminator;
import org.apache.openjpa.jdbc.meta.FieldMapping;
import org.apache.openjpa.jdbc.meta.MappingInfo;
import org.apache.openjpa.jdbc.meta.MappingRepository;
@ -262,6 +264,12 @@ public class AnnotationPersistenceMappingParser
case DISCRIM_VAL:
cm.getDiscriminator().getMappingInfo().setValue
(((DiscriminatorValue) anno).value());
if (Modifier.isAbstract(cm.getDescribedType().
getModifiers()) && getLog().isInfoEnabled()) {
getLog().info(
_loc.get("discriminator-on-abstract-class", cm
.getDescribedType().getName()));
}
break;
case INHERITANCE:
parseInheritance(cm, (Inheritance) anno);
@ -525,18 +533,22 @@ public class AnnotationPersistenceMappingParser
col.setName(dcol.name());
if (!StringUtils.isEmpty(dcol.columnDefinition()))
col.setTypeName(dcol.columnDefinition());
Discriminator discrim = cm.getDiscriminator();
switch (dcol.discriminatorType()) {
case CHAR:
col.setJavaType(JavaTypes.CHAR);
discrim.setJavaType(JavaTypes.CHAR);
break;
case INTEGER:
col.setJavaType(JavaTypes.INT);
if (dcol.length() != 31)
col.setSize(dcol.length());
discrim.setJavaType(JavaTypes.INT);
break;
default:
col.setJavaType(JavaTypes.STRING);
col.setSize(dcol.length());
discrim.setJavaType(JavaTypes.STRING);
}
cm.getDiscriminator().getMappingInfo().setColumns
(Arrays.asList(new Column[]{ col }));

View File

@ -18,6 +18,7 @@
*/
package org.apache.openjpa.persistence.jdbc;
import java.lang.reflect.Modifier;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
@ -197,6 +198,7 @@ public class XMLPersistenceMappingParser
ret = startSecondaryTable(attrs);
break;
case DISCRIM_COL:
parseDiscriminatorColumn(attrs);
_discCol = parseColumn(attrs);
ret = true;
break;
@ -314,21 +316,22 @@ public class XMLPersistenceMappingParser
cm.getMappingInfo().setColumns(_supJoinCols);
if (_discCol != null) {
DiscriminatorMappingInfo dinfo = cm.getDiscriminator().
getMappingInfo();
if (_discType != null) {
DiscriminatorMappingInfo dinfo = cm.getDiscriminator()
.getMappingInfo();
switch (_discType) {
case CHAR:
_discCol.setJavaType(JavaTypes.CHAR);
cm.getDiscriminator().setJavaType(JavaTypes.CHAR);
break;
case INTEGER:
_discCol.setJavaType(JavaTypes.INT);
cm.getDiscriminator().setJavaType(JavaTypes.INT);
break;
default:
_discCol.setJavaType(JavaTypes.STRING);
cm.getDiscriminator().setJavaType(JavaTypes.STRING);
break;
}
}
dinfo.setColumns(Arrays.asList(new Column[]{ _discCol }));
}
clearClassInfo();
@ -439,6 +442,13 @@ public class XMLPersistenceMappingParser
ClassMapping cm = (ClassMapping) currentElement();
cm.getDiscriminator().getMappingInfo().setValue(val);
if (Modifier.isAbstract(cm.getDescribedType().getModifiers())
&& getLog().isInfoEnabled()) {
getLog().info(
_loc.get("discriminator-on-abstract-class", cm
.getDescribedType().getName()));
}
}
/**
@ -916,4 +926,12 @@ public class XMLPersistenceMappingParser
TRUE,
FALSE
}
private void parseDiscriminatorColumn(Attributes attrs) {
String val = attrs.getValue("discriminator-type");
if (val != null) {
_discType = Enum.valueOf(DiscriminatorType.class, val);
}
}
}

View File

@ -48,3 +48,7 @@ not-embedded: Attempt to declare mapping overrides on non-embedded field "{0}".
no-gen-table: No generated table found at "{0}".
empty-unique-column: A unique constraint "{0}" specified in mapping of class \
"{1}" includes an empty column.
discriminator-on-abstract-class: A discriminator value has been specified for \
the abstract class "{0}". The discriminator will never be used and may be \
safely removed.

View File

@ -0,0 +1,53 @@
/*
* 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.
*/
package org.apache.openjpa.persistence.discriminator;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="DISC_COL", discriminatorType=DiscriminatorType.CHAR)
public abstract class CharAbstractEntity {
@Id
@GeneratedValue
private long id;
@Column(length=16)
private String name;
public long getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,36 @@
/*
* 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.
*/
package org.apache.openjpa.persistence.discriminator;
import javax.persistence.Entity;
@Entity(name="chrLeaf")
public class CharLeafEntity
extends CharRootEntity {
private int subInt;
public int getSubInt() {
return subInt;
}
public void setSubInt(int subInt) {
this.subInt = subInt;
}
}

View File

@ -0,0 +1,27 @@
/*
* 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.
*/
package org.apache.openjpa.persistence.discriminator;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue("R")
public class CharRootEntity extends CharAbstractEntity {
}

View File

@ -0,0 +1,54 @@
/*
* 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.
*/
package org.apache.openjpa.persistence.discriminator;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DISC_COL",
discriminatorType = DiscriminatorType.INTEGER)
public abstract class IntegerAbstractEntity {
@Id
@GeneratedValue
private long id;
@Column(length=16)
private String name;
public long getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,36 @@
/*
* 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.
*/
package org.apache.openjpa.persistence.discriminator;
import javax.persistence.Entity;
@Entity(name="intLeaf")
public class IntegerLeafEntity
extends IntegerRootEntity {
private int subInt;
public int getSubInt() {
return subInt;
}
public void setSubInt(int subInt) {
this.subInt = subInt;
}
}

View File

@ -0,0 +1,28 @@
/*
* 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.
*/
package org.apache.openjpa.persistence.discriminator;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue("10101")
public class IntegerRootEntity extends IntegerAbstractEntity {
}

View File

@ -0,0 +1,54 @@
/*
* 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.
*/
package org.apache.openjpa.persistence.discriminator;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DISC_COL",
discriminatorType = DiscriminatorType.STRING)
public abstract class StringAbstractEntity {
@Id
@GeneratedValue
private long id;
@Column(length = 16)
private String name;
public long getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,36 @@
/*
* 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.
*/
package org.apache.openjpa.persistence.discriminator;
import javax.persistence.Entity;
@Entity(name="strLeaf")
public class StringLeafEntity
extends StringRootEntity {
private int subInt;
public int getSubInt() {
return subInt;
}
public void setSubInt(int subInt) {
this.subInt = subInt;
}
}

View File

@ -0,0 +1,27 @@
/*
* 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.
*/
package org.apache.openjpa.persistence.discriminator;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
@Entity
@DiscriminatorValue("StringRoot")
public class StringRootEntity extends StringAbstractEntity {
}

View File

@ -0,0 +1,100 @@
/*
* 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.
*/
package org.apache.openjpa.persistence.discriminator;
import javax.persistence.EntityManager;
import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.meta.Discriminator;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.persistence.OpenJPAPersistence;
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
public class TestDiscriminatorTypes extends SingleEMFTestCase {
protected void setUp() {
super.setUp(CharAbstractEntity.class, CharLeafEntity.class,
CharRootEntity.class, IntegerAbstractEntity.class,
IntegerLeafEntity.class, IntegerRootEntity.class,
StringAbstractEntity.class, StringLeafEntity.class,
StringRootEntity.class);
}
public void testCharDiscriminators() {
EntityManager em = emf.createEntityManager(); // load types
Discriminator discrim = getMapping("CharAbstractEntity")
.getDiscriminator();
assertEquals(new Character('C'), discrim.getValue()); // Generated
assertEquals(JavaTypes.CHAR, discrim.getJavaType());
discrim = getMapping("chrLeaf").getDiscriminator();
assertEquals(new Character('c'), discrim.getValue());
assertEquals(JavaTypes.CHAR, discrim.getJavaType());
discrim = getMapping("CharRootEntity").getDiscriminator();
assertEquals(new Character('R'), discrim.getValue());
assertEquals(JavaTypes.CHAR, discrim.getJavaType());
em.close();
}
public void testIntDiscriminators() {
EntityManager em = emf.createEntityManager(); // load the types
Discriminator discrim = getMapping("IntegerAbstractEntity")
.getDiscriminator();
assertEquals(new Integer("IntegerAbstractEntity".hashCode()), discrim
.getValue()); // Generated value
assertEquals(JavaTypes.INT, discrim.getJavaType());
discrim = getMapping("intLeaf").getDiscriminator();
assertEquals(new Integer("intLeaf".hashCode()), discrim.getValue());
assertEquals(JavaTypes.INT, discrim.getJavaType());
discrim = getMapping("IntegerRootEntity").getDiscriminator();
assertEquals(new Integer(10101), discrim.getValue());
assertEquals(JavaTypes.INT, discrim.getJavaType());
em.close();
}
public void testStringDiscriminators() {
EntityManager em = emf.createEntityManager(); // load the types
Discriminator discrim = getMapping("StringAbstractEntity")
.getDiscriminator();
assertEquals("StringAbstractEntity", discrim.getValue()); // Generated
assertEquals(JavaTypes.STRING, discrim.getJavaType());
discrim = getMapping("strLeaf").getDiscriminator();
assertEquals("strLeaf", discrim.getValue());
assertEquals(JavaTypes.STRING, discrim.getJavaType());
discrim = getMapping("StringRootEntity").getDiscriminator();
assertEquals("StringRoot", discrim.getValue());
assertEquals(JavaTypes.STRING, discrim.getJavaType());
em.close();
}
private ClassMapping getMapping(String name) {
return (ClassMapping) OpenJPAPersistence.cast(emf).getConfiguration()
.getMetaDataRepositoryInstance().getMetaData(name,
getClass().getClassLoader(), true);
}
}