1 package uk.ac.cam.ch.wwmm.opsin;
2 
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.LinkedHashSet;
6 import java.util.List;
7 import java.util.Set;
8 
9 /**
10  * A "struct" to hold the results of fragment building.
11  * @author dl387
12  *
13  */
14 class BuildResults {
15 	/**Holds the atoms that are currently marked as radicals. An atom may be listed twice for say diyl
16 	 * Typically these will be utilised by a word rule e.g. the ethyl of ethyl ethanoate has one
17 	 * Also holds the order of the bond that will be created when it is used (valency)
18 	 * setExplicitly says whether the outAtom absolutely definitely refers to that atom or not.
19 	 * e.g. propyl is stored as prop-1-yl with this set to false while prop-2-yl has it set to true
20 	 * These OutAtoms are the same objects as are present in the fragments*/
21 	private final List<OutAtom> outAtoms = new ArrayList<OutAtom>();
22 
23 	/**The atoms that may be used to from things like esters*/
24 	private final List<FunctionalAtom> functionalAtoms = new ArrayList<FunctionalAtom>();
25 
26 	/**A list of fragments that have been evaluated to form this BuildResults. They are in the order they would be found in the XML*/
27 	private final Set<Fragment> fragments = new LinkedHashSet<Fragment>();
28 
29 	/**A BuildResults is constructed from a list of Fragments.
30 	 * This constructor creates this list from the groups present in an XML word/bracket/sub element.
31      * @param wordSubOrBracket*/
BuildResults(Element wordSubOrBracket)32 	BuildResults(Element wordSubOrBracket) {
33 		List<Element> groups = OpsinTools.getDescendantElementsWithTagName(wordSubOrBracket, XmlDeclarations.GROUP_EL);
34 		for (Element group : groups) {
35 			Fragment frag = group.getFrag();
36 			fragments.add(frag);
37 			for (int i = 0, l = frag.getOutAtomCount(); i < l; i++) {
38 				outAtoms.add(frag.getOutAtom(i));
39 			}
40 			int functionalAtomCount = frag.getFunctionalAtomCount();
41 			if (functionalAtomCount > 0){
42 				Element parent = group.getParent();
43 				if (parent.getName().equals(XmlDeclarations.ROOT_EL) ||
44 						OpsinTools.getNextGroup(group) == null) {
45 					for (int i = 0; i < functionalAtomCount; i++) {
46 						functionalAtoms.add(frag.getFunctionalAtom(i));
47 					}
48 				}
49 			}
50 		}
51 	}
52 
53 	/**
54 	 * Construct a blank buildResults
55 	 */
BuildResults()56 	BuildResults() {}
57 
58 	/**
59 	 * Returns a read only view of the fragments in this BuildResults
60 	 * @return
61 	 */
getFragments()62 	Set<Fragment> getFragments(){
63 		return Collections.unmodifiableSet(fragments);
64 	}
65 
getFragmentCount()66 	int getFragmentCount(){
67 		return fragments.size();
68 	}
69 
getOutAtom(int i)70 	OutAtom getOutAtom(int i) {
71 		return outAtoms.get(i);
72 	}
73 
getOutAtomCount()74 	int getOutAtomCount() {
75 		return outAtoms.size();
76 	}
77 
removeOutAtom(int i)78 	OutAtom removeOutAtom(int i) {
79 		OutAtom outAtom = outAtoms.get(i);
80 		outAtom.getAtom().getFrag().removeOutAtom(outAtom);
81 		return outAtoms.remove(i);
82 	}
83 
removeAllOutAtoms()84 	void removeAllOutAtoms() {
85 		for (int i = outAtoms.size() -1; i >=0 ; i--) {
86 			removeOutAtom(i);
87 		}
88 	}
89 
90 	/**
91 	 * Returns the atom corresponding to position i in the functionalAtoms list
92 	 * @param i index
93 	 * @return atom
94 	 */
getFunctionalAtom(int i)95 	Atom getFunctionalAtom(int i) {
96 		return functionalAtoms.get(i).getAtom();
97 	}
98 
removeFunctionalAtom(int i)99 	FunctionalAtom removeFunctionalAtom(int i) {
100 		FunctionalAtom functionalAtom = functionalAtoms.get(i);
101 		functionalAtom.getAtom().getFrag().removeFunctionalAtom(functionalAtom);
102 		return functionalAtoms.remove(i);
103 	}
104 
getFunctionalAtomCount()105 	int getFunctionalAtomCount(){
106 		return functionalAtoms.size();
107 	}
108 
109 	/**
110 	 * Returns the first OutAtom
111 	 * @return OutAtom
112 	 */
getFirstOutAtom()113 	OutAtom getFirstOutAtom() {
114 		return outAtoms.get(0);
115 	}
116 
117 	/**
118 	 * Returns the atom corresponding to the given id assuming the atom the id corresponds to is within the list of fragment in this Buildresults
119 	 * @param id index
120 	 * @return atom
121 	 * @throws StructureBuildingException
122 	 */
getAtomByIdOrThrow(int id)123 	Atom getAtomByIdOrThrow(int id) throws StructureBuildingException {
124 		for (Fragment fragment : fragments) {
125 			Atom outAtom =fragment.getAtomByID(id);
126 			if (outAtom != null){
127 				return outAtom;
128 			}
129 		}
130 		throw new StructureBuildingException("No fragment contained this id: " + id);
131 	}
132 
mergeBuildResults(BuildResults otherBR)133 	void mergeBuildResults(BuildResults otherBR) {
134 		outAtoms.addAll(otherBR.outAtoms);
135 		functionalAtoms.addAll(otherBR.functionalAtoms);
136 		fragments.addAll(otherBR.fragments);
137 	}
138 
139 	/**
140 	 * Returns the sum of the charges of the fragments in the buildResults
141 	 * @return
142 	 */
getCharge()143 	int getCharge() {
144 		int totalCharge = 0;
145 		for (Fragment frag : fragments) {
146 			totalCharge += frag.getCharge();
147 		}
148 		return totalCharge;
149 	}
150 }
151