free text search: better querying for 'isNotNull' and code harmonization
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / description / StateData.java
index 7ec2b1e07d2771f214b11a11c7ebcb044d8ed9a9..e127170d057b75674d7773fc84422669aa9a9181 100644 (file)
-/**
-* Copyright (C) 2007 EDIT
-* European Distributed Institute of Taxonomy 
-* http://www.e-taxonomy.eu
-* 
-* The contents of this file are subject to the Mozilla Public License Version 1.1
-* See LICENSE.TXT at the top of this package for the full license terms.
-*/
-
-package eu.etaxonomy.cdm.model.description;
-
-
-import eu.etaxonomy.cdm.model.common.Language;
-import eu.etaxonomy.cdm.model.common.LanguageString;
-import eu.etaxonomy.cdm.model.common.MultilanguageSet;
-import eu.etaxonomy.cdm.model.common.VersionableEntity;
-import org.apache.log4j.Logger;
-
-import java.util.*;
-
-import javax.persistence.*;
-
-/**
- * @author m.doering
- * @version 1.0
- * @created 08-Nov-2007 13:06:53
- */
-@Entity
-public class StateData extends VersionableEntity {
-       public StateData() {
-               super();
-               // TODO Auto-generated constructor stub
-       }
-       static Logger logger = Logger.getLogger(StateData.class);
-       private State state;
-       private Set<Modifier> modifiers = new HashSet();
-       private MultilanguageSet modifyingText;
-
-       @ManyToOne
-       public State getState(){
-               return this.state;
-       }
-       public void setState(State state){
-               this.state = state;
-       }
-       
-
-       @OneToMany
-       public Set<Modifier> getModifiers(){
-               return this.modifiers;
-       }
-       private void setModifiers(Set<Modifier> modifiers) {
-               this.modifiers = modifiers;
-       }
-       public void addModifier(Modifier modifier){
-               this.modifiers.add(modifier);
-       }
-       public void removeModifier(Modifier modifier){
-               this.modifiers.remove(modifier);
-       }
-
-
-       public MultilanguageSet getModifyingText(){
-               return this.modifyingText;
-       }
-       private void setModifyingText(MultilanguageSet modifyingText) {
-               this.modifyingText = modifyingText;
-       }
-       public void addModifyingText(String text, Language lang){
-               this.modifyingText.add(text, lang);
-       }
-       public void addModifyingText(LanguageString text){
-               this.modifyingText.add(text);
-       }
-       public void removeModifyingText(Language lang){
-               this.modifyingText.remove(lang);
-       }
-
+/**\r
+* Copyright (C) 2007 EDIT\r
+* European Distributed Institute of Taxonomy\r
+* http://www.e-taxonomy.eu\r
+*\r
+* The contents of this file are subject to the Mozilla Public License Version 1.1\r
+* See LICENSE.TXT at the top of this package for the full license terms.\r
+*/\r
+\r
+package eu.etaxonomy.cdm.model.description;\r
+\r
+\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.Map;\r
+import java.util.Set;\r
+\r
+import javax.persistence.Entity;\r
+import javax.persistence.FetchType;\r
+import javax.persistence.ManyToMany;\r
+import javax.persistence.ManyToOne;\r
+import javax.persistence.OneToMany;\r
+import javax.validation.constraints.NotNull;\r
+import javax.xml.bind.annotation.XmlAccessType;\r
+import javax.xml.bind.annotation.XmlAccessorType;\r
+import javax.xml.bind.annotation.XmlElement;\r
+import javax.xml.bind.annotation.XmlElementWrapper;\r
+import javax.xml.bind.annotation.XmlIDREF;\r
+import javax.xml.bind.annotation.XmlRootElement;\r
+import javax.xml.bind.annotation.XmlSchemaType;\r
+import javax.xml.bind.annotation.XmlType;\r
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.hibernate.annotations.Cascade;\r
+import org.hibernate.annotations.CascadeType;\r
+import org.hibernate.envers.Audited;\r
+import org.hibernate.search.annotations.Field;\r
+import org.hibernate.search.annotations.FieldBridge;\r
+import org.hibernate.search.annotations.IndexedEmbedded;\r
+\r
+import eu.etaxonomy.cdm.hibernate.search.DefinedTermBaseClassBridge;\r
+import eu.etaxonomy.cdm.hibernate.search.MultilanguageTextFieldBridge;\r
+import eu.etaxonomy.cdm.jaxb.MultilanguageTextAdapter;\r
+import eu.etaxonomy.cdm.model.common.IMultiLanguageTextHolder;\r
+import eu.etaxonomy.cdm.model.common.Language;\r
+import eu.etaxonomy.cdm.model.common.LanguageString;\r
+import eu.etaxonomy.cdm.model.common.MultilanguageText;\r
+import eu.etaxonomy.cdm.model.common.TermVocabulary;\r
+import eu.etaxonomy.cdm.model.common.VersionableEntity;\r
+\r
+/**\r
+ * This class represents the assignment of values ({@link State state terms}) to {@link Feature features}\r
+ * corresponding to {@link CategoricalData categorical data}. A state data instance\r
+ * constitutes an atomized part of an information piece (categorical data) so\r
+ * that several state data instances may belong to one categorical data\r
+ * instance.\r
+ * <P>\r
+ * This class corresponds to CharacterStateDataType according to the SDD schema.\r
+ *\r
+ * @author m.doering\r
+ * @version 1.0\r
+ * @created 08-Nov-2007 13:06:53\r
+ */\r
+@XmlAccessorType(XmlAccessType.FIELD)\r
+@XmlType(name = "StateData", propOrder = {\r
+    "state",\r
+    "modifiers",\r
+    "modifyingText"\r
+})\r
+@XmlRootElement(name = "StateData")\r
+@Entity\r
+@Audited\r
+public class StateData extends VersionableEntity implements IModifiable, IMultiLanguageTextHolder, Cloneable{\r
+    private static final long serialVersionUID = -4380314126624505415L;\r
+    private static final Logger logger = Logger.getLogger(StateData.class);\r
+\r
+    @XmlElement(name = "State")\r
+    @XmlIDREF\r
+    @XmlSchemaType(name = "IDREF")\r
+    @ManyToOne(fetch = FetchType.LAZY)\r
+    @IndexedEmbedded\r
+    private State state;\r
+\r
+    @XmlElementWrapper(name = "Modifiers")\r
+    @XmlElement(name = "Modifier")\r
+    @ManyToMany(fetch = FetchType.LAZY)\r
+    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})\r
+    @IndexedEmbedded\r
+//     @NotNull // avoids creating a UNIQUE key for this field -> not needed for ManyToMany\r
+    private Set<Modifier> modifiers = new HashSet<Modifier>();\r
+\r
+    @XmlElement(name = "ModifyingText")\r
+    @XmlJavaTypeAdapter(MultilanguageTextAdapter.class)\r
+    @OneToMany(fetch = FetchType.LAZY)\r
+    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})\r
+    @Field(name="modifyingText")\r
+    @FieldBridge(impl=MultilanguageTextFieldBridge.class)\r
+    private Map<Language,LanguageString> modifyingText = new HashMap<Language,LanguageString>();\r
+\r
+//********************* FACTORY METHODS ************************\\r
+\r
+    /**\r
+     * Creates a new empty state data instance.\r
+     */\r
+    public static StateData NewInstance(){\r
+        return new StateData();\r
+    }\r
+\r
+\r
+    /**\r
+     * Creates a new empty state data instance.\r
+     *\r
+     * <b>NOTE:</b> {@link State}  is a sub class of {@link DefinedTermBase}.\r
+     * If the state passed as parameter has been created newly it <b>has to be persisted before</b> it is possible to save the StateData.\r
+     */\r
+    public static StateData NewInstance(State state){\r
+        StateData stateData = new StateData();\r
+        stateData.setState(state);\r
+        return stateData;\r
+    }\r
+\r
+//*************************** CONSTRUCTOR ************************\\r
+\r
+    /**\r
+     * Class constructor: creates a new empty state data instance.\r
+     */\r
+    public StateData() {\r
+        super();\r
+    }\r
+\r
+//************************** GETTER /SETTER *************************\\r
+\r
+    /**\r
+     * Returns the {@link State state term} used in <i>this</i> state data.\r
+     */\r
+    public State getState(){\r
+        return this.state;\r
+    }\r
+    /**\r
+     * @see    #getState()\r
+     */\r
+    public void setState(State state){\r
+        this.state = state;\r
+    }\r
+\r
+\r
+    /**\r
+     * Returns the set of {@link Modifier modifiers} used to qualify the validity\r
+     * of <i>this</i> state data. This is only metainformation.\r
+     */\r
+    public Set<Modifier> getModifiers(){\r
+        return this.modifiers;\r
+    }\r
+\r
+    /**\r
+     * Adds a {@link Modifier modifier} to the set of {@link #getModifiers() modifiers}\r
+     * used to qualify the validity of <i>this</i> state data.\r
+     *\r
+     * @param modifier the modifier to be added to <i>this</i> state data\r
+     * @see                            #getModifiers()\r
+     */\r
+    public void addModifier(Modifier modifier){\r
+        this.modifiers.add(modifier);\r
+    }\r
+    /**\r
+     * Removes one element from the set of {@link #getModifiers() modifiers}\r
+     * used to qualify the validity of <i>this</i> state data.\r
+     *\r
+     * @param  modifier        the modifier which should be removed\r
+     * @see                    #getModifiers()\r
+     * @see                    #addModifier(Modifier)\r
+     */\r
+    public void removeModifier(Modifier modifier){\r
+        this.modifiers.remove(modifier);\r
+    }\r
+\r
+\r
+    /**\r
+     * Returns the {@link MultilanguageText multilanguage text} used to qualify the validity\r
+     * of <i>this</i> state data.  The different {@link LanguageString language strings}\r
+     * contained in the multilanguage text should all have the same meaning.<BR>\r
+     * A multilanguage text does not belong to a controlled {@link TermVocabulary term vocabulary}\r
+     * as a {@link Modifier modifier} does.\r
+     * <P>\r
+     * NOTE: the actual content of <i>this</i> state data is NOT\r
+     * stored in the modifying text. This is only metainformation\r
+     * (like "Some experts express doubt about this assertion").\r
+     */\r
+    public Map<Language,LanguageString> getModifyingText(){\r
+        return this.modifyingText;\r
+    }\r
+\r
+    /**\r
+     * Creates a {@link LanguageString language string} based on the given text string\r
+     * and the given {@link Language language} and adds it to the {@link MultilanguageText multilanguage text}\r
+     * used to qualify the validity of <i>this</i> state data.\r
+     *\r
+     *\r
+     * @param text             the string describing the validity\r
+     *                                         in a particular language\r
+     * @param language the language in which the text string is formulated\r
+     *\r
+     * @see                            #getModifyingText()\r
+     * @see                            #putModifyingText(LanguageString)\r
+     * @deprecated             should follow the put semantic of maps, this method will be removed in v4.0\r
+     *                                         Use the {@link #putModifyingText(Language, String) putModifyingText} method instead\r
+     */\r
+    @Deprecated\r
+    public LanguageString addModifyingText(String text, Language language){\r
+        return this.putModifyingText(language, text);\r
+    }\r
+\r
+    /**\r
+     * Creates a {@link LanguageString language string} based on the given text string\r
+     * and the given {@link Language language} and adds it to the {@link MultilanguageText multilanguage text}\r
+     * used to qualify the validity of <i>this</i> state data.\r
+     *\r
+     * @param language the language in which the text string is formulated\r
+     * @param text             the string describing the validity\r
+     *                                         in a particular language\r
+     *\r
+     * @see                            #getModifyingText()\r
+     * @see                            #addModifyingText(LanguageString)\r
+     */\r
+    public LanguageString putModifyingText(Language language, String text){\r
+        return this.modifyingText.put(language, LanguageString.NewInstance(text, language));\r
+    }\r
+    /**\r
+     * Adds a translated {@link LanguageString text in a particular language}\r
+     * to the {@link MultilanguageText multilanguage text} used to qualify the validity\r
+     * of <i>this</i> state data.\r
+     *\r
+     * @param text     the language string describing the validity\r
+     *                                 in a particular language\r
+     * @see                    #getModifyingText()\r
+     * @see                    #putModifyingText(Language, String)\r
+     * @deprecated     should follow the put semantic of maps, this method will be removed in v4.0\r
+     *                                 Use the {@link #putModifyingText(LanguagString) putModifyingText} method instead\r
+     */\r
+    @Deprecated\r
+    public LanguageString addModifyingText(LanguageString text){\r
+        return this.putModifyingText(text);\r
+    }\r
+\r
+    /**\r
+     * Adds a translated {@link LanguageString text in a particular language}\r
+     * to the {@link MultilanguageText multilanguage text} used to qualify the validity\r
+     * of <i>this</i> state data.\r
+     *\r
+     * @param text     the language string describing the validity\r
+     *                                 in a particular language\r
+     * @see                    #getModifyingText()\r
+     * @see                    #putModifyingText(Language, String)\r
+     */\r
+    public LanguageString putModifyingText(LanguageString text){\r
+        return this.modifyingText.put(text.getLanguage(),text);\r
+    }\r
+    /**\r
+     * Removes from the {@link MultilanguageText multilanguage text} used to qualify the validity\r
+     * of <i>this</i> state data the one {@link LanguageString language string}\r
+     * with the given {@link Language language}.\r
+     *\r
+     * @param  lang    the language in which the language string to be removed\r
+     *                                 has been formulated\r
+     * @see            #getModifyingText()\r
+     */\r
+    public LanguageString removeModifyingText(Language lang){\r
+        return this.modifyingText.remove(lang);\r
+    }\r
+\r
+//*********************************** CLONE *****************************************/\r
+\r
+    /**\r
+     * Clones <i>this</i> state data. This is a shortcut that enables to create\r
+     * a new instance that differs only slightly from <i>this</i> state data by\r
+     * modifying only some of the attributes.\r
+     *\r
+     * @see eu.etaxonomy.cdm.model.common.VersionableEntity#clone()\r
+     * @see java.lang.Object#clone()\r
+     */\r
+    @Override\r
+    public Object clone() {\r
+\r
+        try {\r
+            StateData result = (StateData)super.clone();\r
+\r
+            //modifiers\r
+            result.modifiers = new HashSet<Modifier>();\r
+            for (Modifier modifier : getModifiers()){\r
+                result.modifiers.add(modifier);\r
+            }\r
+\r
+            //modifying text\r
+            result.modifyingText = new HashMap<Language, LanguageString>();\r
+            for (Language language : getModifyingText().keySet()){\r
+                //TODO clone needed? See also IndividualsAssociation\r
+                LanguageString newLanguageString = (LanguageString)getModifyingText().get(language).clone();\r
+                result.modifyingText.put(language, newLanguageString);\r
+            }\r
+\r
+            return result;\r
+            //no changes to: state\r
+        } catch (CloneNotSupportedException e) {\r
+            logger.warn("Object does not implement cloneable");\r
+            e.printStackTrace();\r
+            return null;\r
+        }\r
+    }\r
 }
\ No newline at end of file