View Javadoc

1   
2   package org.molwind.chemical.model;
3   
4   /*
5    * This file is part of Molwind.
6    *
7    * Molwind is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU General Public License as published by
9    * the Free Software Foundation, either version 3 of the License, or
10   * (at your option) any later version.
11   *
12   * Molwind is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15   * GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with Molwind. If not, see <http://www.gnu.org/licenses/>.
19   */
20  
21  import org.molwind.graph.DefaultEntityGraph;
22  import org.molwind.graph.EntityGraph;
23  import org.molwind.graph.EntityGraphAnalyzer;
24  import org.molwind.graph.EntityVertex;
25  import org.molwind.model.Identity;
26  import org.molwind.model.PartOf;
27  import org.molwind.model.Relationship;
28  import org.molwind.model.RelationshipResolver;
29  import org.molwind.model.WorldEntity;
30  import org.molwind.util.MolwindLogger;
31  import org.openscience.cdk.tools.MFAnalyser;
32  
33  import org.openscience.cdk.interfaces.IMolecule;
34  
35  /**
36   * SubstructureResolver resolves substructure relationships.
37   *
38   * @author <a href="mailto:oliver.karch@molwind.org">Oliver Karch</a>
39   * @version 1.0
40   */
41  public class SubstructureResolver
42  implements RelationshipResolver, EntityGraphAnalyzer, Identity {
43  
44      
45      
46      private EntityGraph compounds;
47      private boolean analyzed;
48      
49      private String idName;
50     
51      private String parentName;
52  
53      /**
54       * Get the ParentName value.
55       * @return the ParentName value.
56       */
57      public String getParentName(){
58  
59  	return parentName;
60      }
61  
62      /**
63       * Set the ParentName value.
64       * @param newParentName The new ParentName value.
65       */
66      public void setParentName(String newParentName) {
67  	this.parentName = newParentName;
68      }
69  
70      
71  
72      /**
73       * Creates a new Substructure resolver which uses the given attributes to
74       * decide whether there is a relationship.
75       *
76       * @param newParentName
77       *      the parent attribute's name
78       * @param newIdName
79       *      the id attribute's name
80       */
81      public SubstructureResolver(final String newParentName,
82              final String newIdName) {
83          parentName = newParentName;
84  
85          idName = newIdName;
86          analyzed = false;
87          compounds = new DefaultEntityGraph();
88      }
89      
90  
91      private  double getMolecularWeight(IMolecule molecule){
92  	if(molecule==null) return 0.0F;
93  	
94  	MFAnalyser mfa = new MFAnalyser(molecule);
95  	try {
96  	    return mfa.getCanonicalMass();
97  	} catch (Exception e) {
98  	    return 0.0f;
99  	}
100 	
101 	
102 	
103     }
104     
105  
106 
107 
108     private String getId(final ChemicalEntity chemicalEntity) {
109         String id = chemicalEntity.getAttribute(idName);
110 
111         if (id == null) {
112             id = String.valueOf(System.currentTimeMillis());
113             chemicalEntity.setAttribute(idName, id);
114         }
115         return id;
116     }
117 
118     private boolean addRelation(final ChemicalEntity chemicalEntity1,
119             final ChemicalEntity chemicalEntity2) {
120         if ((chemicalEntity1 == null) || (chemicalEntity2 == null)) {
121             return false;
122         }
123 
124         PartOf relation = new PartOf(chemicalEntity1, chemicalEntity2);
125         chemicalEntity1.addRelationship(relation);
126         chemicalEntity2.addRelationship(relation);
127 
128         String id1 = getId(chemicalEntity1);
129         String id2 = getId(chemicalEntity2);
130 	
131 	IMolecule molecule1 = chemicalEntity1.getMolecule();
132 	IMolecule molecule2 = chemicalEntity2.getMolecule();
133 	
134 	int edgeWeight = molecule1.getAtomCount()+molecule2.getAtomCount();
135 
136         compounds.addEntity(id1, chemicalEntity1);
137         compounds.addEntity(id2, chemicalEntity2);
138         compounds.addEdge(id1, id2, relation,edgeWeight);
139 
140 
141         return true;
142     }
143 
144 
145     /**
146      * Augments the relationship between two entities.
147      *
148      * @param entity1
149      *      a world entity
150      * @param entity2
151      *      another world entity
152      * @return
153      *      true if any relationship could be established, false otherwise
154      */
155     public boolean related(final WorldEntity entity1,
156             final WorldEntity entity2) {
157 
158         if ((entity1 == null)
159                 || (entity2 == null)
160                 || !(entity1 instanceof ChemicalEntity)
161                 || !(entity2 instanceof ChemicalEntity)) {
162             return false;
163         }
164 
165         ChemicalEntity chemicalEntity1 = (ChemicalEntity) entity1;
166         ChemicalEntity chemicalEntity2 = (ChemicalEntity) entity2;
167         String parentId1 = chemicalEntity1.getAttribute(parentName);
168         String id1 = getId(chemicalEntity1);
169         String parentId2 = chemicalEntity2.getAttribute(parentName);
170         String id2 = getId(chemicalEntity2);
171 
172 	       
173 	 
174 	boolean related = false;
175         if (parentId1 != null) {
176             if (parentId1.equals(id2)) {
177                 return addRelation(chemicalEntity1, chemicalEntity2);
178             } else {
179                 related = addRelation(chemicalEntity1,
180                         (ChemicalEntity) compounds.findEntity(parentId1));
181             }
182         }
183 
184         if (parentId2 != null) {
185             if (parentId2.equals(id1)) {
186                 return addRelation(chemicalEntity2, chemicalEntity1);
187             } else {
188                 related = addRelation(chemicalEntity2,
189                         (ChemicalEntity) compounds.findEntity(parentId2));
190             }
191         }
192 
193         if (!related) {
194             compounds.addEntity(id1, chemicalEntity1);
195             compounds.addEntity(id2, chemicalEntity2);
196         }
197 
198         return false;
199     }
200 
201     /**
202      * Resolves the relationships by creating a graph of entity vertices and
203      * relationship edges.
204      *
205      * @return
206      *      the resulting entity graph
207      */
208     public EntityGraph resolve() {
209         if (!analyzed) {
210             compounds.analyze(this);
211             analyzed = true;
212         }
213         return compounds;
214     }
215 
216     /**
217      * Analyzes an entity graph.
218      *
219      * @param graph
220      *      the graph to be analyzed
221      * @param vertex
222      *      the current vertex
223      * @return
224      *      returning false stops analysis immediately
225      */
226     public boolean analyze(final EntityGraph graph,
227             final EntityVertex vertex) {
228         ChemicalEntity chemicalEntity1 = (ChemicalEntity) vertex.getEntity();
229         String parentId = chemicalEntity1.getAttribute(parentName);
230         if (parentId == null) {
231             return true;
232         }
233 
234         ChemicalEntity chemicalEntity2 =
235             (ChemicalEntity) graph.findEntity(parentId);
236         if (chemicalEntity2 == null) {
237             MolwindLogger.warn("Missing parent id " + parentId, null);
238             return true;
239         }
240 
241         Relationship[] relations =
242             chemicalEntity1.hasRelationship(chemicalEntity2);
243         if (relations.length > 0) {
244             return true;
245         }
246 
247         PartOf relation = new PartOf(chemicalEntity1, chemicalEntity2);
248         chemicalEntity1.addRelationship(relation);
249         chemicalEntity2.addRelationship(relation);
250         return true;
251     }
252 
253     /**
254      * Tests whether two entities are identical.
255      *
256      * @param entity1
257      *      the first entity
258      * @param entity2
259      *      the second entity
260      * @return
261      *      true if the two entities are identical
262      */
263     public boolean identical(final WorldEntity entity1,
264             final WorldEntity entity2) {
265         String id1 = getId((ChemicalEntity) entity1);
266         String id2 = getId((ChemicalEntity) entity2);
267         return id1.equals(id2);
268     }
269 
270 }