001/* 002 * (C) Copyright 2014 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 * Benoit Delbosc 018 */ 019package org.nuxeo.ecm.platform.query.core; 020 021import java.util.ArrayList; 022import java.util.Arrays; 023import java.util.Collections; 024import java.util.HashMap; 025import java.util.List; 026import java.util.Map; 027 028import org.codehaus.jackson.annotate.JsonIgnore; 029import org.nuxeo.ecm.core.api.DocumentModel; 030import org.nuxeo.ecm.platform.query.api.Aggregate; 031import org.nuxeo.ecm.platform.query.api.AggregateDefinition; 032import org.nuxeo.ecm.platform.query.api.AggregateRangeDateDefinition; 033import org.nuxeo.ecm.platform.query.api.AggregateRangeDefinition; 034import org.nuxeo.ecm.platform.query.api.Bucket; 035import org.nuxeo.ecm.platform.query.api.PredicateFieldDefinition; 036 037/** 038 * @since 6.0 039 */ 040public class AggregateBase<B extends Bucket> implements Aggregate<B> { 041 042 protected final AggregateDefinition definition; 043 044 protected final DocumentModel searchDocument; 045 046 protected List<String> selection; 047 048 protected List<B> buckets; 049 050 protected List<Bucket> extendedBuckets; 051 052 protected Map<String, Bucket> bucketMap = null; 053 054 public AggregateBase(AggregateDefinition definition, DocumentModel searchDocument) { 055 assert (definition != null); 056 this.definition = definition; 057 this.searchDocument = searchDocument; 058 } 059 060 @Override 061 public String getId() { 062 return definition.getId(); 063 } 064 065 @Override 066 public String getType() { 067 return definition.getType(); 068 } 069 070 @Override 071 public String getField() { 072 return definition.getDocumentField(); 073 } 074 075 @Override 076 public Map<String, String> getProperties() { 077 return definition.getProperties(); 078 } 079 080 @Override 081 public List<AggregateRangeDefinition> getRanges() { 082 return definition.getRanges(); 083 } 084 085 @Override 086 public List<AggregateRangeDateDefinition> getDateRanges() { 087 return definition.getDateRanges(); 088 } 089 090 @SuppressWarnings("unchecked") 091 @Override 092 public List<String> getSelection() { 093 if (selection == null) { 094 PredicateFieldDefinition field = definition.getSearchField(); 095 if (searchDocument != null) { 096 // property must be nxs:stringList 097 List<String> value = null; 098 Object resolvedProperties = searchDocument.getProperty(field.getSchema(), field.getName()); 099 if (resolvedProperties instanceof String[]) { 100 value = Arrays.asList((String[]) resolvedProperties); 101 } else if (resolvedProperties instanceof List<?>) { 102 value = (List<String>) searchDocument.getProperty(field.getSchema(), field.getName()); 103 } 104 selection = value; 105 } 106 if (selection == null) { 107 selection = Collections.<String> emptyList(); 108 } 109 } 110 return selection; 111 } 112 113 @Override 114 public void setSelection(List<String> selection) { 115 this.selection = selection; 116 } 117 118 @Override 119 public List<B> getBuckets() { 120 return buckets; 121 } 122 123 @Override 124 public List<Bucket> getExtendedBuckets() { 125 if (extendedBuckets == null) { 126 extendedBuckets = new ArrayList<Bucket>(); 127 final List<String> currentSelection = getSelection(); 128 if (currentSelection != null) { 129 for (String s : currentSelection) { 130 if (!hasBucket(s)) { 131 extendedBuckets.add(new MockBucket(s)); 132 } 133 } 134 } 135 extendedBuckets.addAll(buckets); 136 } 137 return extendedBuckets; 138 } 139 140 @Override 141 public void setBuckets(List<B> buckets) { 142 this.buckets = buckets; 143 this.bucketMap = null; 144 this.extendedBuckets = null; 145 } 146 147 @JsonIgnore 148 public DocumentModel getSearchDocument() { 149 return searchDocument; 150 } 151 152 @Override 153 public String toString() { 154 return String.format("Aggregate(%s, %s, %s, %s, %s)", getId(), getType(), getField(), 155 (getSelection() != null) ? Arrays.toString(getSelection().toArray()) : null, 156 (buckets != null) ? Arrays.toString(buckets.toArray()) : null); 157 } 158 159 @Override 160 public boolean hasBucket(final String key) { 161 return getBucketMap().containsKey(key); 162 } 163 164 @Override 165 public Bucket getBucket(final String key) { 166 return getBucketMap().get(key); 167 } 168 169 public Map<String, Bucket> getBucketMap() { 170 if (bucketMap == null && getBuckets() != null) { 171 bucketMap = new HashMap<String, Bucket>(); 172 for (Bucket b : getBuckets()) { 173 bucketMap.put(b.getKey(), b); 174 } 175 } 176 return bucketMap; 177 } 178 179 @Override 180 public void resetSelection() { 181 PredicateFieldDefinition field = definition.getSearchField(); 182 if (searchDocument != null) { 183 searchDocument.setProperty(field.getSchema(), field.getName(), null); 184 selection = Collections.<String> emptyList(); 185 } 186 } 187 188}