Index: main/plugin-odf/src/org/ametys/odf/OdfXSLTHelper.java =================================================================== --- main/plugin-odf/src/org/ametys/odf/OdfXSLTHelper.java (revision 37442) +++ main/plugin-odf/src/org/ametys/odf/OdfXSLTHelper.java (working copy) @@ -15,14 +15,17 @@ */ package org.ametys.odf; -import org.apache.avalon.framework.service.ServiceException; -import org.apache.avalon.framework.service.ServiceManager; -import org.apache.avalon.framework.service.Serviceable; - import org.ametys.odf.enumeration.OdfEnumerationConstant; import org.ametys.odf.enumeration.OdfEnumerationHelper; import org.ametys.odf.enumeration.OdfEnumerationI18nCache; +import org.ametys.odf.program.SubProgram; +import org.ametys.odf.xslt.SubProgramElement; +import org.ametys.plugins.repository.AmetysObjectResolver; import org.ametys.runtime.config.Config; +import org.apache.avalon.framework.service.ServiceException; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.avalon.framework.service.Serviceable; +import org.w3c.dom.Node; /** * Helper component to be used from XSL stylesheets. @@ -31,12 +34,14 @@ { private static OdfEnumerationI18nCache _i18nCache; private static OdfEnumerationHelper _enumerationHelper; + private static AmetysObjectResolver _ametysObjectResolver; @Override public void service(ServiceManager smanager) throws ServiceException { _i18nCache = (OdfEnumerationI18nCache) smanager.lookup(OdfEnumerationI18nCache.ROLE); _enumerationHelper = (OdfEnumerationHelper) smanager.lookup(OdfEnumerationHelper.ROLE); + _ametysObjectResolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE); } /** @@ -50,4 +55,15 @@ String label = _i18nCache.getTranslatedValue(OdfEnumerationConstant.DEGREE, Config.getInstance().getValueAsString("odf.programs.lang"), code); return label != null ? label : code; } + + /** + * Get the structure of a subprogram. + * @param subprogramId + * @return Node with the structure + */ + public static Node getSubProgram (String subprogramId) + { + SubProgram subProgram = _ametysObjectResolver.resolveById(subprogramId); + return new SubProgramElement(subProgram, _ametysObjectResolver); + } } Index: main/plugin-odf/src/org/ametys/odf/xslt/AbstractODFElement.java =================================================================== --- main/plugin-odf/src/org/ametys/odf/xslt/AbstractODFElement.java (revision 0) +++ main/plugin-odf/src/org/ametys/odf/xslt/AbstractODFElement.java (revision 0) @@ -0,0 +1,164 @@ +/* + * Copyright 2015 Anyware Services + * + * Licensed 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.ametys.odf.xslt; + +import org.ametys.odf.courselist.CourseList; +import org.ametys.odf.program.Container; +import org.ametys.odf.program.SubProgram; +import org.ametys.plugins.repository.AmetysObject; +import org.ametys.plugins.repository.AmetysObjectIterable; +import org.ametys.plugins.repository.AmetysObjectResolver; +import org.ametys.plugins.repository.TraversableAmetysObject; +import org.ametys.plugins.repository.jcr.SimpleAmetysObject; +import org.ametys.runtime.util.dom.AbstractAmetysElement; +import org.w3c.dom.DOMException; +import org.w3c.dom.Node; + +/** + * DOM layer on structure of an ODF content. + */ +public abstract class AbstractODFElement> extends AbstractAmetysElement +{ + protected int _depth; + protected AmetysObjectResolver _resolver; + + /** + * Constructor. + * @param odfContent the underlying. + * @param depth Depth to SAX. + * @param parent Parent of the element + * @param resolver AmetysObjectResolver to find some elements by ID + */ + public AbstractODFElement(T odfContent, int depth, AbstractODFElement parent, AmetysObjectResolver resolver) + { + super(odfContent, parent); + _depth = depth; + _resolver = resolver; + } + + @Override + public boolean hasChildNodes() + { + if (_depth > 0) + { + if (_object instanceof TraversableAmetysObject) + { + AmetysObjectIterable children = ((TraversableAmetysObject) _object).getChildren(); + for (AmetysObject ao : children) + { + if (ao instanceof Container || ao instanceof CourseList || ao instanceof SubProgram) + { + return true; + } + } + } + else + { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "hasChildNodes"); + } + } + return false; + } + + @Override + public Node getFirstChild() + { + if (_object instanceof TraversableAmetysObject) + { + AmetysObjectIterable children = ((TraversableAmetysObject) _object).getChildren(); + for (AmetysObject ao : children) + { + if (ao instanceof SubProgram) + { + return new SubProgramElement((SubProgram) ao, _depth - 1, this, _resolver); + } + else if (ao instanceof Container) + { + return new ContainerElement((Container) ao, _depth, this, _resolver); + } + else if (ao instanceof CourseList) + { + return new CourseListElement((CourseList) ao, _depth, this, _resolver); + } + } + } + else + { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "getFirstChild"); + } + + return null; + } + + @Override + public Node getNextSibling() + { + if (_parent == null) + { + return null; + } + + AbstractODFElement parentElement = (AbstractODFElement) _parent; + Object parent = parentElement.getWrappedObject(); + + if (parent instanceof TraversableAmetysObject) + { + AmetysObjectIterable children = ((TraversableAmetysObject) parent).getChildren(); + + boolean isNext = false; + AmetysObject nextSibling = null; + + while (nextSibling == null && children.hasNext()) + { + AmetysObject ao = children.next(); + + if (isNext) + { + if (ao instanceof SubProgram || ao instanceof Container || ao instanceof CourseList) + { + nextSibling = ao; + } + } + else if (_object.getId().equals(ao.getId())) + { + isNext = true; + } + } + + if (nextSibling != null) + { + if (nextSibling instanceof SubProgram) + { + return new SubProgramElement((SubProgram) nextSibling, _depth - 1, parentElement, _resolver); + } + else if (nextSibling instanceof Container) + { + return new ContainerElement((Container) nextSibling, _depth, parentElement, _resolver); + } + else if (nextSibling instanceof CourseList) + { + return new CourseListElement((CourseList) nextSibling, _depth, parentElement, _resolver); + } + } + } + else + { + throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "getFirstChild"); + } + + return null; + } +} Index: main/plugin-odf/src/org/ametys/odf/xslt/ContainerElement.java =================================================================== --- main/plugin-odf/src/org/ametys/odf/xslt/ContainerElement.java (revision 0) +++ main/plugin-odf/src/org/ametys/odf/xslt/ContainerElement.java (revision 0) @@ -0,0 +1,71 @@ +/* + * Copyright 2015 Anyware Services + * + * Licensed 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.ametys.odf.xslt; + +import java.util.HashMap; +import java.util.Map; + +import org.ametys.odf.program.Container; +import org.ametys.plugins.repository.AmetysObjectResolver; +import org.ametys.runtime.util.dom.AmetysAttribute; +import org.apache.commons.lang.StringUtils; + +/** + * DOM layer on structure of {@link Container}. + */ +public class ContainerElement extends AbstractODFElement +{ + /** + * Constructor. + * @param container the underlying {@link Container}. + * @param depth Depth to SAX. + * @param parent Parent of the element + * @param resolver AmetysObjectResolver to find some elements by ID + */ + public ContainerElement(Container container, int depth, AbstractODFElement parent, AmetysObjectResolver resolver) + { + super(container, depth, parent, resolver); + } + + @Override + public String getTagName() + { + return "container"; + } + + @Override + protected Map _lookupAttributes() + { + Map result = new HashMap(); + + result.put("title", new AmetysAttribute("title", "title", null, _object.getTitle(), this)); + result.put("id", new AmetysAttribute("id", "id", null, _object.getId(), this)); + + String code = _object.getCode(); + if (StringUtils.isNotEmpty(code)) + { + result.put("code", new AmetysAttribute("code", "code", null, code, this)); + } + + String ects = _object.getEcts(); + if (StringUtils.isNotEmpty(ects)) + { + result.put("ects", new AmetysAttribute("ects", "ects", null, ects, this)); + } + + return result; + } +} Index: main/plugin-odf/src/org/ametys/odf/xslt/CourseElement.java =================================================================== --- main/plugin-odf/src/org/ametys/odf/xslt/CourseElement.java (revision 0) +++ main/plugin-odf/src/org/ametys/odf/xslt/CourseElement.java (revision 0) @@ -0,0 +1,115 @@ +/* + * Copyright 2015 Anyware Services + * + * Licensed 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.ametys.odf.xslt; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.ametys.odf.course.Course; +import org.ametys.odf.courselist.CourseList; +import org.ametys.plugins.repository.AmetysObjectResolver; +import org.ametys.plugins.repository.UnknownAmetysObjectException; +import org.ametys.runtime.util.dom.AmetysAttribute; +import org.w3c.dom.Node; + +/** + * DOM layer on structure of {@link Course}. + */ +public class CourseElement extends AbstractODFElement +{ + /** + * Constructor. + * @param course the underlying {@link Course}. + * @param depth Depth to SAX. + * @param parent Parent of the element + * @param resolver AmetysObjectResolver to find some elements by ID + */ + public CourseElement(Course course, int depth, CourseListElement parent, AmetysObjectResolver resolver) + { + super(course, depth, parent, resolver); + } + + @Override + public String getTagName() + { + return "course"; + } + + @Override + protected Map _lookupAttributes() + { + Map result = new HashMap(); + + result.put("title", new AmetysAttribute("title", "title", null, _object.getTitle(), this)); + result.put("id", new AmetysAttribute("id", "id", null, _object.getId(), this)); + result.put("code", new AmetysAttribute("code", "code", null, _object.getElpCode(), this)); + result.put("name", new AmetysAttribute("name", "name", null, _object.getName(), this)); + + String parentPath = _object.getContextPath(); + if (parentPath != null) + { + result.put("path", new AmetysAttribute("path", "path", null, parentPath + "/" + _object.getName() + "-" + _object.getElpCode(), this)); + } + + return result; + } + + @Override + public Node getNextSibling() + { + if (_parent == null) + { + return null; + } + + CourseListElement parentElement = (CourseListElement) _parent; + CourseList parent = parentElement.getWrappedObject(); + + List courseIds = parent.getCourses(); + + boolean isNext = false; + Course nextSibling = null; + int i = 0; + + while (nextSibling == null && i < courseIds.size()) + { + String courseId = courseIds.get(i++); + if (isNext) + { + try + { + nextSibling = _resolver.resolveById(courseId); + } + catch (UnknownAmetysObjectException e) + { + // TODO + } + } + else if (courseId.equals(_object.getId())) + { + isNext = true; + } + } + + if (nextSibling != null) + { + return new CourseElement(nextSibling, _depth, parentElement, _resolver); + } + + return null; + } +} Index: main/plugin-odf/src/org/ametys/odf/xslt/CourseListElement.java =================================================================== --- main/plugin-odf/src/org/ametys/odf/xslt/CourseListElement.java (revision 0) +++ main/plugin-odf/src/org/ametys/odf/xslt/CourseListElement.java (revision 0) @@ -0,0 +1,128 @@ +/* + * Copyright 2015 Anyware Services + * + * Licensed 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.ametys.odf.xslt; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.ametys.odf.course.Course; +import org.ametys.odf.courselist.CourseList; +import org.ametys.odf.courselist.CourseList.ChoiceType; +import org.ametys.plugins.repository.AmetysObjectResolver; +import org.ametys.plugins.repository.UnknownAmetysObjectException; +import org.ametys.runtime.util.dom.AmetysAttribute; +import org.apache.commons.lang.StringUtils; +import org.w3c.dom.Node; + +/** + * DOM layer on structure of {@link CourseList}. + */ +public class CourseListElement extends AbstractODFElement +{ + /** + * Constructor. + * @param courseList the underlying {@link CourseList}. + * @param depth Depth to SAX. + * @param resolver AmetysObjectResolver to find some elements by ID + */ + public CourseListElement(CourseList courseList, int depth, AbstractODFElement parent, AmetysObjectResolver resolver) + { + super(courseList, depth, parent, resolver); + } + + @Override + public String getTagName() + { + return "courseList"; + } + + @Override + protected Map _lookupAttributes() + { + Map result = new HashMap(); + + result.put("title", new AmetysAttribute("title", "title", null, _object.getTitle(), this)); + + String code = _object.getCode(); + if (StringUtils.isNotEmpty(code)) + { + result.put("code", new AmetysAttribute("code", "code", null, code, this)); + } + + String ects = _object.getEcts(); + if (StringUtils.isNotEmpty(ects)) + { + result.put("ects", new AmetysAttribute("ects", "ects", null, ects, this)); + } + + ChoiceType type = _object.getType(); + if (type != null) + { + result.put("type", new AmetysAttribute("type", "type", null, type.toString(), this)); + } + + if (ChoiceType.CHOICE.equals(type)) + { + result.put("min", new AmetysAttribute("min", "min", null, String.valueOf(_object.getMinNumberOfCourses()), this)); + result.put("max", new AmetysAttribute("max", "max", null, String.valueOf(_object.getMaxNumberOfCourses()), this)); + } + + return result; + } + + @Override + public boolean hasChildNodes() + { + if (_depth > 0) + { + List courseIds = _object.getCourses(); + for (String courseId : courseIds) + { + try + { + _resolver.resolveById(courseId); + return true; + } + catch (UnknownAmetysObjectException e) + { + // TODO + } + } + } + return false; + } + + @Override + public Node getFirstChild() + { + List courseIds = _object.getCourses(); + for (String courseId : courseIds) + { + try + { + Course course = _resolver.resolveById(courseId); + return new CourseElement(course, _depth, this, _resolver); + } + catch (UnknownAmetysObjectException e) + { + // TODO + } + } + + return null; + } +} Index: main/plugin-odf/src/org/ametys/odf/xslt/SubProgramElement.java =================================================================== --- main/plugin-odf/src/org/ametys/odf/xslt/SubProgramElement.java (revision 0) +++ main/plugin-odf/src/org/ametys/odf/xslt/SubProgramElement.java (revision 0) @@ -0,0 +1,87 @@ +/* + * Copyright 2015 Anyware Services + * + * Licensed 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.ametys.odf.xslt; + +import java.util.HashMap; +import java.util.Map; + +import org.ametys.odf.program.SubProgram; +import org.ametys.plugins.repository.AmetysObjectResolver; +import org.ametys.runtime.util.dom.AmetysAttribute; +import org.apache.commons.lang.StringUtils; + +/** + * DOM layer on structure of {@link SubProgram}. + */ +public class SubProgramElement extends AbstractODFElement +{ + /** + * Constructor. + * @param subProgram the underlying {@link SubProgram}. + * @param depth Depth to SAX. + * @param parent Parent of the element + * @param resolver AmetysObjectResolver to find some elements by ID + */ + public SubProgramElement(SubProgram subProgram, int depth, AbstractODFElement parent, AmetysObjectResolver resolver) + { + super(subProgram, depth, parent, resolver); + } + + /** + * Constructor. + * @param container the underlying {@link SubProgram}. + * @param resolver AmetysObjectResolver to find some elements by ID + */ + public SubProgramElement(SubProgram subProgram, AmetysObjectResolver resolver) + { + this(subProgram, 1, null, resolver); + } + + @Override + public String getTagName() + { + return "subprogram"; + } + + @Override + protected Map _lookupAttributes() + { + Map result = new HashMap(); + + result.put("title", new AmetysAttribute("title", "title", null, _object.getTitle(), this)); + result.put("id", new AmetysAttribute("id", "id", null, _object.getId(), this)); + + String code = _object.getCode(); + if (StringUtils.isNotEmpty(code)) + { + result.put("code", new AmetysAttribute("code", "code", null, code, this)); + } + + String ects = _object.getEcts(); + if (StringUtils.isNotEmpty(ects)) + { + result.put("ects", new AmetysAttribute("ects", "ects", null, ects, this)); + } + + String parentPath = _object.getContextPath(); + if (parentPath != null) + { + result.put("path", new AmetysAttribute("path", "path", null, parentPath + "/" + _object.getName(), this)); + } + + return result; + } +}