001/* 002 * Copyright 2015 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.odf.xslt; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.List; 021import java.util.Map; 022 023import org.apache.commons.lang.StringUtils; 024import org.w3c.dom.DOMException; 025import org.w3c.dom.Node; 026 027import org.ametys.core.util.dom.AbstractWrappingAmetysElement; 028import org.ametys.core.util.dom.AmetysAttribute; 029import org.ametys.odf.ProgramItem; 030import org.ametys.odf.course.Course; 031import org.ametys.odf.courselist.CourseList; 032import org.ametys.odf.program.Container; 033import org.ametys.odf.program.ProgramPart; 034import org.ametys.odf.program.SubProgram; 035import org.ametys.odf.program.TraversableProgramPart; 036import org.ametys.plugins.repository.AmetysObject; 037import org.ametys.plugins.repository.AmetysObjectResolver; 038 039/** 040 * DOM layer on structure of an ODF content. 041 * @param <T> The type of wrapped object 042 */ 043public abstract class AbstractODFElement<T extends ProgramItem> extends AbstractWrappingAmetysElement<T> 044{ 045 /** The children depth */ 046 protected int _depth; 047 /** The Ametys object resolver */ 048 protected AmetysObjectResolver _resolver; 049 050 /** 051 * Constructor. 052 * @param odfContent the underlying. 053 * @param depth Depth to SAX. 054 * @param parent Parent of the element 055 * @param resolver AmetysObjectResolver to find some elements by ID 056 */ 057 public AbstractODFElement(T odfContent, int depth, AbstractODFElement<?> parent, AmetysObjectResolver resolver) 058 { 059 super(odfContent, parent); 060 _depth = depth; 061 _resolver = resolver; 062 } 063 064 @Override 065 public boolean hasChildNodes() 066 { 067 if (_depth == 0) 068 { 069 // Stop recursion 070 return false; 071 } 072 073 if (_object instanceof CourseList) 074 { 075 return ((CourseList) _object).hasCourses(); 076 } 077 else if (_object instanceof TraversableProgramPart) 078 { 079 return ((TraversableProgramPart) _object).hasProgramPartChildren(); 080 } 081 else if (_object instanceof Course) 082 { 083 return ((Course) _object).hasCourseLists(); 084 } 085 else 086 { 087 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "hasChildNodes"); 088 } 089 } 090 091 @Override 092 public Node getFirstChild() 093 { 094 if (_object instanceof CourseList) 095 { 096 List<Course> courses = ((CourseList) _object).getCourses(); 097 if (courses.size() > 0) 098 { 099 return new CourseElement(courses.get(0), 1, (CourseListElement) this, _resolver); 100 } 101 } 102 else if (_object instanceof TraversableProgramPart) 103 { 104 List<ProgramPart> children = ((TraversableProgramPart) _object).getProgramPartChildren(); 105 if (children.size() > 0) 106 { 107 ProgramPart ao = children.get(0); 108 if (ao instanceof SubProgram) 109 { 110 return new SubProgramElement((SubProgram) ao, _depth - 1, this, _resolver); 111 } 112 else if (ao instanceof Container) 113 { 114 return new ContainerElement((Container) ao, _depth - 1, this, _resolver); 115 } 116 else if (ao instanceof CourseList) 117 { 118 return new CourseListElement((CourseList) ao, _depth - 1, this, _resolver); 119 } 120 } 121 return null; 122 } 123 else if (_object instanceof Course) 124 { 125 List<CourseList> children = ((Course) _object).getCourseLists(); 126 if (children.size() > 0) 127 { 128 CourseList ao = children.get(0); 129 return new CourseListElement(ao, _depth - 1, this, _resolver); 130 } 131 } 132 else 133 { 134 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "getFirstChild"); 135 } 136 137 return null; 138 } 139 140 @Override 141 public Node getNextSibling() 142 { 143 if (_parent == null) 144 { 145 return null; 146 } 147 148 AmetysObject nextSibling = null; 149 150 AbstractODFElement<?> parentElement = (AbstractODFElement<?>) _parent; 151 Object parent = parentElement.getWrappedObject(); 152 if (parent instanceof ProgramPart) 153 { 154 List<AmetysObject> children = new ArrayList<>(); 155 if (parent instanceof TraversableProgramPart) 156 { 157 children.addAll(((TraversableProgramPart) parent).getProgramPartChildren()); 158 } 159 if (parent instanceof CourseList) 160 { 161 children.addAll(((CourseList) parent).getCourses()); 162 } 163 164 boolean isNext = false; 165 int count = 0; 166 167 while (nextSibling == null && count < children.size()) 168 { 169 if (isNext) 170 { 171 nextSibling = children.get(count); 172 } 173 else if (_object.getId().equals(children.get(count).getId())) 174 { 175 isNext = true; 176 } 177 count++; 178 } 179 } 180 else if (parent instanceof Course) 181 { 182 List<CourseList> children = ((Course) parent).getCourseLists(); 183 184 boolean isNext = false; 185 int count = 0; 186 187 while (nextSibling == null && count < children.size()) 188 { 189 if (isNext) 190 { 191 nextSibling = children.get(count); 192 } 193 else if (_object.getId().equals(children.get(count).getId())) 194 { 195 isNext = true; 196 } 197 count++; 198 } 199 } 200 else 201 { 202 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "getNextSibling"); 203 } 204 205 if (nextSibling != null) 206 { 207 if (nextSibling instanceof SubProgram) 208 { 209 return new SubProgramElement((SubProgram) nextSibling, _depth, parentElement, _resolver); 210 } 211 else if (nextSibling instanceof Container) 212 { 213 return new ContainerElement((Container) nextSibling, _depth, parentElement, _resolver); 214 } 215 else if (nextSibling instanceof CourseList) 216 { 217 return new CourseListElement((CourseList) nextSibling, _depth, parentElement, _resolver); 218 } 219 else if (nextSibling instanceof Course) 220 { 221 return new CourseElement((Course) nextSibling, _depth, (CourseListElement) parentElement, _resolver); 222 } 223 } 224 225 return null; 226 } 227 228 @Override 229 protected Map<String, AmetysAttribute> _lookupAttributes() 230 { 231 Map<String, AmetysAttribute> result = new HashMap<>(); 232 result.put("id", new AmetysAttribute("id", "id", null, _object.getId(), this)); 233 234 if (StringUtils.isNotEmpty(_object.getCode())) 235 { 236 result.put("code", new AmetysAttribute("code", "code", null, _object.getCode(), this)); 237 } 238 if (StringUtils.isNotEmpty(_object.getCatalog())) 239 { 240 result.put("catalog", new AmetysAttribute("catalog", "catalog", null, _object.getCatalog(), this)); 241 } 242 return result; 243 } 244}