001: /*
002:
003: This software is OSI Certified Open Source Software.
004: OSI Certified is a certification mark of the Open Source Initiative.
005:
006: The license (Mozilla version 1.0) can be read at the MMBase site.
007: See http://www.MMBase.org/license
008:
009: */
010:
011: package org.mmbase.bridge.implementation;
012:
013: import java.util.*;
014: import org.mmbase.bridge.*;
015: import org.mmbase.bridge.util.*;
016: import org.mmbase.datatypes.*;
017: import org.mmbase.core.CoreField;
018: import org.mmbase.core.util.Fields;
019: import org.mmbase.module.core.*;
020: import org.mmbase.storage.search.*;
021: import org.mmbase.util.logging.*;
022:
023: /**
024: * This class represents a virtual node type information object.
025: * It has the same functionality as BasicNodeType, but it's nodes are vitrtual - that is,
026: * constructed based on the results of a search over multiple node managers.
027: * As such, it is not possible to search on this node type, nor to create new nodes.
028: * It's sole function is to provide a type definition for the results of a search.
029: * @author Rob Vermeulen
030: * @author Pierre van Rooden
031: * @version $Id: VirtualNodeManager.java,v 1.50 2008/02/27 12:37:50 michiel Exp $
032: */
033: public class VirtualNodeManager extends AbstractNodeManager implements
034: NodeManager {
035: private static final Logger log = Logging
036: .getLoggerInstance(VirtualNodeManager.class);
037:
038: private static final boolean allowNonQueriedFields = true; // not yet configurable
039:
040: // field types
041: final protected Map<String, Field> fieldTypes = new HashMap<String, Field>();
042:
043: final MMObjectBuilder builder;
044: private SearchQuery query;
045:
046: /**
047: * Instantiated a Virtual NodeManager, and tries its best to find reasonable values for the field-types.
048: */
049: VirtualNodeManager(org.mmbase.module.core.VirtualNode node,
050: Cloud cloud) {
051: super (cloud);
052: // determine fields and field types
053: if (node.getBuilder() instanceof VirtualBuilder) {
054: VirtualBuilder virtualBuilder = (VirtualBuilder) node
055: .getBuilder();
056: ;
057: Map<String, CoreField> fields = virtualBuilder
058: .getFields(node);
059: for (Map.Entry<String, CoreField> entry : fields.entrySet()) {
060: Field ft = new BasicField(entry.getValue(), this );
061: fieldTypes.put(entry.getKey(), ft);
062: }
063: builder = null;
064: setStringValue("name", "virtual builder");
065: setStringValue("description", "virtual builder");
066: } else {
067: builder = node.getBuilder();
068: BasicNodeManager.sync(builder, fieldTypes, this );
069: }
070: }
071:
072: /**
073: * @since MMBase-1.8
074: */
075: VirtualNodeManager(Query query, Cloud cloud) {
076: super (cloud);
077: if (query instanceof NodeQuery) {
078: builder = BasicCloudContext.mmb
079: .getBuilder(((NodeQuery) query).getNodeManager()
080: .getName());
081: BasicNodeManager.sync(builder, fieldTypes, this );
082: } else {
083: builder = null;
084: if (log.isDebugEnabled()) {
085: log.debug("Creating NodeManager for " + query.toSql());
086: }
087: // fieldTypes map will be filled 'lazily' on first call to getFieldTypes.
088: this .query = query; // query instanceof BasicQuery ? ((BasicQuery ) query).getQuery() : query;
089: setStringValue("name", "cluster builder");
090: setStringValue("description", "cluster builder");
091: }
092:
093: }
094:
095: /**
096:
097: /**
098: * Returns the fieldlist of this nodemanager after making sure the manager is synced with the builder.
099: * @since MMBase-1.8
100: */
101: @Override
102: protected Map<String, Field> getFieldTypes() {
103: if (builder != null) {
104: return fieldTypes;
105: } else {
106: if (query != null) { // means not yet called (lazy loading of fields)
107: // code to solve the fields.
108: for (Step step : query.getSteps()) {
109: DataType nodeType = DataTypes.getDataType("node");
110: String name = step.getAlias();
111: if (name == null)
112: name = step.getTableName();
113: CoreField fd = Fields.createField(name,
114: Field.TYPE_NODE, Field.TYPE_UNKNOWN,
115: Field.STATE_VIRTUAL, nodeType);
116: fd.finish();
117: Field ft = new VirtualNodeManagerField(fd, name);
118: fieldTypes.put(name, ft);
119:
120: if (allowNonQueriedFields && !query.isAggregating()) {
121: /// if hasField returns true also for unqueried fields
122: FieldIterator fields = cloud.getNodeManager(
123: step.getTableName()).getFields()
124: .fieldIterator();
125: while (fields.hasNext()) {
126: Field f = fields.nextField();
127: final String fieldName = name + "."
128: + f.getName();
129: fieldTypes.put(fieldName,
130: new VirtualNodeManagerField(f,
131: fieldName));
132: }
133: }
134: }
135: if (!allowNonQueriedFields || query.isAggregating()) {
136: //hasField only returns true for queried fields
137: for (StepField field : query.getFields()) {
138: Step step = field.getStep();
139: Field f = cloud.getNodeManager(
140: step.getTableName()).getField(
141: field.getFieldName());
142: String name = field.getAlias();
143: if (name == null) {
144: name = step.getAlias();
145: if (name == null)
146: name = step.getTableName();
147: name += "." + field.getFieldName();
148: }
149: final String fieldName = name;
150: fieldTypes.put(name,
151: new VirtualNodeManagerField(f,
152: fieldName));
153:
154: }
155: }
156: query = null;
157: }
158: return fieldTypes;
159: }
160: }
161:
162: @Override
163: public String getGUIName(int plurality, Locale locale) {
164: if (locale == null)
165: locale = cloud.getLocale();
166: if (builder != null) {
167: if (plurality == NodeManager.GUI_SINGULAR) {
168: return builder.getSingularName(locale.getLanguage());
169: } else {
170: return builder.getPluralName(locale.getLanguage());
171: }
172: } else {
173: return getName();
174: }
175: }
176:
177: @Override
178: public String getName() {
179: return builder == null ? getStringValue("name") : builder
180: .getTableName();
181: }
182:
183: @Override
184: public String getDescription() {
185: return getDescription(null);
186: }
187:
188: @Override
189: public String getDescription(Locale locale) {
190: if (builder == null)
191: return getStringValue("description");
192: if (locale == null)
193: locale = cloud.getLocale();
194: return builder.getDescription(locale.getLanguage());
195: }
196:
197: /**
198: */
199: private class VirtualNodeManagerField extends FieldWrapper {
200:
201: private final String name;
202:
203: VirtualNodeManagerField(Field field, String name) {
204: super (field);
205: this .name = name;
206: }
207:
208: @Override
209: public NodeManager getNodeManager() {
210: return VirtualNodeManager.this ;
211: }
212:
213: @Override
214: public String getName() {
215: return name;
216: }
217:
218: public int compareTo(Field o) {
219: return name.compareTo(o.getName());
220: }
221: }
222:
223: }
|