001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 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 * Contributors: 017 * bstefanescu 018 * 019 * $Id$ 020 */ 021 022package org.nuxeo.ecm.platform.rendering.api; 023 024import java.util.ArrayList; 025import java.util.Arrays; 026import java.util.Calendar; 027import java.util.Collection; 028import java.util.HashMap; 029import java.util.Map; 030 031import org.nuxeo.ecm.core.api.Blob; 032import org.nuxeo.ecm.core.api.Blobs; 033import org.nuxeo.ecm.core.api.CoreSession; 034import org.nuxeo.ecm.core.api.DocumentModel; 035import org.nuxeo.ecm.core.api.PropertyException; 036import org.nuxeo.ecm.core.api.model.PropertyNotFoundException; 037import org.nuxeo.ecm.core.schema.FacetNames; 038import org.nuxeo.ecm.platform.rendering.fm.adapters.SchemaTemplate; 039 040/** 041 * Base class to build views for Document oriented contexts (contexts that are bound to a document). 042 * <p> 043 * Note that this class cannot be used with contexts for which the {@code RenderingContext#getDocument()} method is 044 * returning null. 045 * <p> 046 * This implementation ensure that the context argument is never used so it can be used outside the scope of a rendering 047 * context to get a view over the document. 048 * 049 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 050 */ 051public class DefaultDocumentView implements DocumentView { 052 053 // Must be returned by get() method when the key is unknown since the caller 054 // should be able to 055 // treat differently a key hit that returned null from a key that is not 056 // known by this view 057 public static final Object UNKNOWN = new Object(); 058 059 public interface Field { 060 String getName(); 061 062 Object getValue(DocumentModel doc); 063 } 064 065 protected final Map<String, Field> fields; 066 067 public DefaultDocumentView() { 068 fields = new HashMap<>(); 069 initialize(); 070 } 071 072 public DefaultDocumentView(Map<String, Field> fields) { 073 this.fields = fields == null ? new HashMap<>() : fields; 074 } 075 076 protected void initialize() { 077 addField(SESSION); 078 079 addField(ID); 080 addField(NAME); 081 addField(PATH); 082 addField(TYPE); 083 addField(SID); 084 addField(REPOSITORY); 085 086 addField(SCHEMAS); 087 addField(FACETS); 088 addField(LOCKED); 089 addField(LIFE_CYCLE_STATE); 090 addField(LIFE_CYCLE_POLICY); 091 addField(ALLOWED_STATE_TRANSITIONS); 092 addField(IS_FOLDER); 093 addField(TITLE); 094 addField(AUTHOR); 095 addField(CREATED); 096 addField(MODIFIED); 097 addField(CONTENT); 098 099 addField(PARENT); 100 addField(CHILDREN); 101 addField(REF); 102 addField(VERSIONS); 103 addField(PROXIES); 104 addField(VERSION_LABEL); 105 addField(SOURCE_ID); 106 } 107 108 public final void addField(Field field) { 109 fields.put(field.getName(), field); 110 } 111 112 public final void addFields(Collection<Field> fields) { 113 for (Field field : fields) { 114 this.fields.put(field.getName(), field); 115 } 116 } 117 118 public final void removeField(String name) { 119 fields.remove(name); 120 } 121 122 public Field getField(String name) { 123 return fields.get(name); 124 } 125 126 @Override 127 public Object get(DocumentModel doc, String name) throws PropertyException { 128 Field field = fields.get(name); 129 if (field != null) { 130 return field.getValue(doc); 131 } 132 // may be a a property xpath 133 if (name.indexOf(':') > -1) { 134 return doc.getProperty(name); 135 } 136 // may be a schema name 137 if (doc.hasSchema(name)) { 138 return new SchemaTemplate.DocumentSchema(doc, name); 139 } 140 return UNKNOWN; 141 } 142 143 @Override 144 public Collection<String> keys(DocumentModel doc) { 145 Collection<String> keys = new ArrayList<>(fields.keySet()); 146 keys.addAll(Arrays.asList(doc.getSchemas())); 147 return keys; 148 } 149 150 public Map<String, Field> getFields() { 151 return fields; 152 } 153 154 public boolean isEmpty() { 155 return fields.isEmpty(); 156 } 157 158 public int size(DocumentModel doc) { 159 return fields.size() + doc.getSchemas().length; 160 } 161 162 protected static final Field SESSION = new Field() { 163 @Override 164 public final String getName() { 165 return "session"; 166 } 167 168 @Override 169 public Object getValue(DocumentModel doc) { 170 return doc.getCoreSession(); 171 } 172 }; 173 174 protected static final Field ID = new Field() { 175 @Override 176 public final String getName() { 177 return "id"; 178 } 179 180 @Override 181 public Object getValue(DocumentModel doc) { 182 return doc.getId(); 183 } 184 }; 185 186 protected static final Field NAME = new Field() { 187 @Override 188 public final String getName() { 189 return "name"; 190 } 191 192 @Override 193 public Object getValue(DocumentModel doc) { 194 return doc.getName(); 195 } 196 }; 197 198 protected static final Field PATH = new Field() { 199 @Override 200 public final String getName() { 201 return "path"; 202 } 203 204 @Override 205 public Object getValue(DocumentModel doc) { 206 return doc.getPathAsString(); 207 } 208 }; 209 210 protected static final Field TYPE = new Field() { 211 @Override 212 public final String getName() { 213 return "type"; 214 } 215 216 @Override 217 public Object getValue(DocumentModel doc) { 218 return doc.getType(); 219 } 220 }; 221 222 protected static final Field SCHEMAS = new Field() { 223 @Override 224 public final String getName() { 225 return "schemas"; 226 } 227 228 @Override 229 public Object getValue(DocumentModel doc) { 230 return doc.getSchemas(); 231 } 232 }; 233 234 protected static final Field FACETS = new Field() { 235 @Override 236 public final String getName() { 237 return "facets"; 238 } 239 240 @Override 241 public Object getValue(DocumentModel doc) { 242 return doc.getFacets(); 243 } 244 }; 245 246 protected static final Field STATE = new Field() { 247 @Override 248 public final String getName() { 249 return "state"; 250 } 251 252 @Override 253 public Object getValue(DocumentModel doc) { 254 return doc.getCurrentLifeCycleState(); 255 } 256 }; 257 258 protected static final Field LOCKED = new Field() { 259 @Override 260 public final String getName() { 261 return "isLocked"; 262 } 263 264 @Override 265 public Object getValue(DocumentModel doc) { 266 return doc.isLocked(); 267 } 268 }; 269 270 protected static final Field LIFE_CYCLE_STATE = new Field() { 271 @Override 272 public final String getName() { 273 return "lifeCycleState"; 274 } 275 276 @Override 277 public Object getValue(DocumentModel doc) { 278 return doc.getCurrentLifeCycleState(); 279 } 280 }; 281 282 protected static final Field LIFE_CYCLE_POLICY = new Field() { 283 @Override 284 public final String getName() { 285 return "lifeCyclePolicy"; 286 } 287 288 @Override 289 public Object getValue(DocumentModel doc) { 290 return doc.getLifeCyclePolicy(); 291 } 292 }; 293 294 protected static final Field ALLOWED_STATE_TRANSITIONS = new Field() { 295 @Override 296 public final String getName() { 297 return "allowedStateTransitions"; 298 } 299 300 @Override 301 public Object getValue(DocumentModel doc) { 302 return doc.getAllowedStateTransitions(); 303 } 304 }; 305 306 protected static final Field IS_FOLDER = new Field() { 307 @Override 308 public final String getName() { 309 return "isFolder"; 310 } 311 312 @Override 313 public Object getValue(DocumentModel doc) { 314 return doc.getFacets().contains(FacetNames.FOLDERISH); 315 } 316 }; 317 318 protected static final Field TITLE = new Field() { 319 @Override 320 public String getName() { 321 return "title"; 322 } 323 324 @Override 325 public Object getValue(DocumentModel doc) { 326 return doc.getTitle(); 327 } 328 }; 329 330 protected static final Field AUTHOR = new Field() { 331 @Override 332 public String getName() { 333 return "author"; 334 } 335 336 @Override 337 public Object getValue(DocumentModel doc) { 338 try { 339 return doc.getPropertyValue("dc:creator"); 340 } catch (PropertyNotFoundException e) { 341 // ignore 342 } 343 return null; 344 } 345 }; 346 347 protected static final Field CREATED = new Field() { 348 @Override 349 public String getName() { 350 return "created"; 351 } 352 353 @Override 354 public Object getValue(DocumentModel doc) { 355 try { 356 Calendar cal = (Calendar) doc.getPropertyValue("dc:created"); 357 if (cal != null) { 358 return cal.getTime(); 359 } 360 } catch (PropertyNotFoundException e) { 361 // ignore 362 } 363 return null; 364 } 365 }; 366 367 protected static final Field MODIFIED = new Field() { 368 @Override 369 public String getName() { 370 return "modified"; 371 } 372 373 @Override 374 public Object getValue(DocumentModel doc) { 375 try { 376 Calendar cal = (Calendar) doc.getPropertyValue("dc:modified"); 377 if (cal != null) { 378 return cal.getTime(); 379 } 380 } catch (PropertyNotFoundException e) { 381 // ignore 382 } 383 return null; 384 } 385 }; 386 387 protected static final Field CONTENT = new Field() { 388 @Override 389 public String getName() { 390 return "content"; 391 } 392 393 @Override 394 public Object getValue(DocumentModel doc) { 395 try { 396 Blob blob = (Blob) doc.getPropertyValue("file:content"); 397 if (blob != null) { 398 return blob; 399 } 400 } catch (PropertyNotFoundException e) { 401 // ignore 402 } 403 return Blobs.createBlob(""); 404 } 405 }; 406 407 /** @deprecated since 11.1 */ 408 @Deprecated 409 protected static final Field SID = new Field() { 410 @Override 411 public String getName() { 412 return "sessionId"; 413 } 414 415 @Override 416 public Object getValue(DocumentModel doc) { 417 return ""; 418 } 419 }; 420 421 protected static final Field REPOSITORY = new Field() { 422 @Override 423 public String getName() { 424 return "repository"; 425 } 426 427 @Override 428 public Object getValue(DocumentModel doc) { 429 return doc.getRepositoryName(); 430 } 431 }; 432 433 protected static final Field PARENT = new Field() { 434 @Override 435 public String getName() { 436 return "parent"; 437 } 438 439 @Override 440 public Object getValue(DocumentModel doc) { 441 CoreSession session = doc.getCoreSession(); 442 return session.getParentDocument(doc.getRef()); 443 } 444 }; 445 446 protected static final Field CHILDREN = new Field() { 447 @Override 448 public String getName() { 449 return "children"; 450 } 451 452 @Override 453 public Object getValue(DocumentModel doc) { 454 CoreSession session = doc.getCoreSession(); 455 return session.getChildren(doc.getRef()); 456 } 457 }; 458 459 protected static final Field REF = new Field() { 460 @Override 461 public String getName() { 462 return "ref"; 463 } 464 465 @Override 466 public Object getValue(DocumentModel doc) { 467 return doc.getRef(); 468 } 469 }; 470 471 protected static final Field VERSIONS = new Field() { 472 @Override 473 public String getName() { 474 return "versions"; 475 } 476 477 @Override 478 public Object getValue(DocumentModel doc) { 479 CoreSession session = doc.getCoreSession(); 480 return session.getVersions(doc.getRef()); 481 } 482 }; 483 484 protected static final Field PROXIES = new Field() { 485 @Override 486 public String getName() { 487 return "proxies"; 488 } 489 490 @Override 491 public Object getValue(DocumentModel doc) { 492 CoreSession session = doc.getCoreSession(); 493 return session.getProxies(doc.getRef(), null); 494 } 495 }; 496 497 protected static final Field VERSION_LABEL = new Field() { 498 @Override 499 public String getName() { 500 return "versionLabel"; 501 } 502 503 @Override 504 public Object getValue(DocumentModel doc) { 505 return doc.getVersionLabel(); 506 } 507 }; 508 509 protected static final Field SOURCE_ID = new Field() { 510 @Override 511 public String getName() { 512 return "sourceId"; 513 } 514 515 @Override 516 public Object getValue(DocumentModel doc) { 517 return doc.getSourceId(); 518 } 519 }; 520 521 /** 522 * The singleton instance that should be used by clients. Warn that this static field must be defined at the end of 523 * the class after any other field class since it will try to register these fields (otherwise fields will not be 524 * defined yet at the time of the initialization of that static member 525 */ 526 public static final DefaultDocumentView DEFAULT = new DefaultDocumentView(); 527 528}