001/* 002 * Copyright 2010 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 */ 016 017package org.ametys.cms.content; 018 019import java.io.IOException; 020import java.util.ArrayList; 021import java.util.List; 022import java.util.Map; 023import java.util.Optional; 024 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.avalon.framework.service.ServiceManager; 027import org.apache.cocoon.ProcessingException; 028import org.apache.cocoon.environment.ObjectModelHelper; 029import org.apache.cocoon.generation.ServiceableGenerator; 030import org.apache.cocoon.xml.AttributesImpl; 031import org.apache.cocoon.xml.XMLUtils; 032import org.apache.commons.lang3.StringUtils; 033import org.xml.sax.SAXException; 034 035import org.ametys.cms.content.references.OutgoingReferences; 036import org.ametys.cms.contenttype.ContentTypesHelper; 037import org.ametys.cms.repository.Content; 038import org.ametys.cms.transformation.ConsistencyChecker; 039import org.ametys.cms.transformation.ConsistencyChecker.CHECK; 040import org.ametys.cms.transformation.ConsistencyChecker.CheckReport; 041import org.ametys.plugins.repository.AmetysObjectResolver; 042import org.ametys.plugins.repository.UnknownAmetysObjectException; 043import org.ametys.plugins.repository.data.type.ModelItemTypeConstants; 044import org.ametys.runtime.i18n.I18nizableText; 045import org.ametys.runtime.model.ModelHelper; 046import org.ametys.runtime.model.ModelItem; 047import org.ametys.runtime.model.exception.UndefinedItemPathException; 048 049/** 050 * Generates the consistency report for the given content 051 */ 052public class ConsistencyGenerator extends ServiceableGenerator 053{ 054 /** Repository content */ 055 protected AmetysObjectResolver _resolver; 056 /** The consistency checker */ 057 protected ConsistencyChecker _consistencyChecker; 058 /** The content types helper */ 059 protected ContentTypesHelper _contentTypesHelper; 060 /** The content helper */ 061 protected ContentHelper _contentHelper; 062 063 @Override 064 public void service(ServiceManager smanager) throws ServiceException 065 { 066 super.service(smanager); 067 _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE); 068 _consistencyChecker = (ConsistencyChecker) smanager.lookup(ConsistencyChecker.ROLE); 069 _contentTypesHelper = (ContentTypesHelper) smanager.lookup(ContentTypesHelper.ROLE); 070 _contentHelper = (ContentHelper) smanager.lookup(ContentHelper.ROLE); 071 } 072 073 @Override 074 public void generate() throws IOException, SAXException, ProcessingException 075 { 076 contentHandler.startDocument(); 077 XMLUtils.startElement(contentHandler, "contents"); 078 079 @SuppressWarnings("unchecked") 080 Map<String, Object> jsParameters = (Map<String, Object>) objectModel.get(ObjectModelHelper.PARENT_CONTEXT); 081 @SuppressWarnings("unchecked") 082 List<String> contentsId = (List<String>) jsParameters.get("contentsId"); 083 for (String contentId : contentsId) 084 { 085 try 086 { 087 Content content = _resolver.resolveById(contentId); 088 089 AttributesImpl attrs = new AttributesImpl(); 090 attrs.addCDATAAttribute("id", content.getId()); 091 attrs.addCDATAAttribute("title", _contentHelper.getTitle(content)); 092 attrs.addCDATAAttribute("name", content.getName()); 093 attrs.addCDATAAttribute("path", content.getPath()); 094 attrs.addCDATAAttribute("type", StringUtils.join(content.getTypes(), ',')); 095 if (content.getLanguage() != null) 096 { 097 attrs.addCDATAAttribute("lang", content.getLanguage()); 098 } 099 100 XMLUtils.startElement(contentHandler, "content", attrs); 101 102 List<ModelItem> modelItemsToSax = new ArrayList<>(); 103 Map<String, OutgoingReferences> referencesByPath = content.getOutgoingReferences(); 104 105 for (String dataPath : referencesByPath.keySet()) 106 { 107 try 108 { 109 List<ModelItem> modelItemPath = _contentTypesHelper.getModelItemPath(dataPath, content); 110 111 // Add these model items to the set of model items to SAX. 112 modelItemsToSax.addAll(modelItemPath); 113 114 saxReferencesConsistency(content, referencesByPath.get(dataPath), dataPath); 115 } 116 catch (UndefinedItemPathException e) 117 { 118 getLogger().warn("Trying to check consistency for a item path that doesn't exist in the model. Reference will be ignored", e); 119 } 120 } 121 122 // SAX model items used for this content 123 for (ModelItem modelItem : modelItemsToSax) 124 { 125 attrs.clear(); 126 attrs.addCDATAAttribute("path", modelItem.getPath()); 127 attrs.addCDATAAttribute("is-repeater", Boolean.toString(ModelItemTypeConstants.REPEATER_TYPE_ID.equals(modelItem.getType().getId()))); 128 XMLUtils.startElement(contentHandler, "metadata-definition", attrs); 129 modelItem.getLabel().toSAX(contentHandler); 130 XMLUtils.endElement(contentHandler, "metadata-definition"); 131 } 132 133 XMLUtils.endElement(contentHandler, "content"); 134 } 135 catch (UnknownAmetysObjectException e) 136 { 137 getLogger().warn("Can not check consistency of non existing content '" + contentId + "'"); 138 } 139 } 140 141 XMLUtils.endElement(contentHandler, "contents"); 142 contentHandler.endDocument(); 143 } 144 145 /** 146 * Check consistency for each outgoing references and generate SAX event for the result. 147 * @param content the content containing the references 148 * @param references the outgoing references 149 * @param dataPath the path of the data containing the outgoing references 150 * @throws SAXException if an error occurred 151 */ 152 protected void saxReferencesConsistency(Content content, OutgoingReferences references, String dataPath) throws SAXException 153 { 154 // SAX'ing consistency info 155 String definitionPath = ModelHelper.getDefinitionPathFromDataPath(dataPath); 156 for (String referenceType : references.keySet()) 157 { 158 for (String referenceValue : references.get(referenceType)) 159 { 160 AttributesImpl attrs = new AttributesImpl(); 161 attrs.addCDATAAttribute("type", referenceType); 162 attrs.addCDATAAttribute("element", referenceValue); 163 attrs.addCDATAAttribute("path", definitionPath); 164 165 CheckReport report; 166 try 167 { 168 report = _consistencyChecker.checkConsistency(referenceType, referenceValue, content.getId(), dataPath, false); 169 } 170 catch (Exception e) 171 { 172 // Consider it a failure. 173 report = new CheckReport(CHECK.SERVER_ERROR, Optional.ofNullable(e.getMessage())); 174 } 175 176 String elementName; 177 switch (report.status()) 178 { 179 case SUCCESS: 180 elementName = "success"; 181 break; 182 case UNKNOWN: 183 elementName = "unknown"; 184 break; 185 case UNAUTHORIZED: 186 elementName = "unauthorized"; 187 break; 188 case NOT_FOUND: 189 elementName = "not-found"; 190 break; 191 case SERVER_ERROR: 192 default: 193 elementName = "server-error"; 194 break; 195 } 196 XMLUtils.startElement(contentHandler, elementName, attrs); 197 I18nizableText label = _consistencyChecker.getLabel(referenceType, referenceValue, content.getId(), dataPath); 198 label.toSAX(contentHandler, "label"); 199 if (report.message().isPresent()) 200 { 201 XMLUtils.createElement(contentHandler, "message", report.message().get()); 202 } 203 XMLUtils.endElement(contentHandler, elementName); 204 } 205 } 206 } 207}