001: /*
002: * $Id: ModelViewEntity.java,v 1.11 2003/12/17 19:29:08 jonesde Exp $
003: *
004: * Copyright (c) 2001, 2002 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: */
024: package org.ofbiz.entity.model;
025:
026: import java.util.*;
027: import org.w3c.dom.*;
028:
029: import org.ofbiz.base.util.*;
030: import org.ofbiz.entity.jdbc.*;
031:
032: /**
033: * This class extends ModelEntity and provides additional information appropriate to view entities
034: *
035: * @author <a href="mailto:jonesde@ofbiz.org">David E. Jones</a>
036: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
037: * @author <a href="mailto:peterm@miraculum.com">Peter Moon</a>
038: * @version $Revision: 1.11 $
039: * @since 2.0
040: */
041: public class ModelViewEntity extends ModelEntity {
042: public static final String module = ModelViewEntity.class.getName();
043:
044: public static Map functionPrefixMap = new HashMap();
045: static {
046: functionPrefixMap.put("min", "MIN(");
047: functionPrefixMap.put("max", "MAX(");
048: functionPrefixMap.put("sum", "SUM(");
049: functionPrefixMap.put("avg", "AVG(");
050: functionPrefixMap.put("count", "COUNT(");
051: functionPrefixMap.put("count-distinct", "COUNT(DISTINCT ");
052: functionPrefixMap.put("upper", "UPPER(");
053: functionPrefixMap.put("lower", "LOWER(");
054: }
055:
056: /** Contains member-entity alias name definitions: key is alias, value is ModelMemberEntity */
057: protected Map memberModelMemberEntities = new HashMap();
058:
059: /** A list of all ModelMemberEntity entries; this is mainly used to preserve the original order of member entities from the XML file */
060: protected List allModelMemberEntities = new LinkedList();
061:
062: /** Contains member-entity ModelEntities: key is alias, value is ModelEntity; populated with fields */
063: protected Map memberModelEntities = null;
064:
065: /** List of alias-alls which act as a shortcut for easily pulling over member entity fields */
066: protected List aliasAlls = new ArrayList();
067:
068: /** List of aliases with information in addition to what is in the standard field list */
069: protected List aliases = new ArrayList();
070:
071: /** List of view links to define how entities are connected (or "joined") */
072: protected List viewLinks = new ArrayList();
073:
074: /** A List of the Field objects for the View Entity, one for each GROUP BY field */
075: protected List groupBys = new ArrayList();
076:
077: public ModelViewEntity(ModelReader reader, Element entityElement,
078: Element docElement, UtilTimer utilTimer,
079: Hashtable docElementValues) {
080: this .modelReader = reader;
081:
082: if (utilTimer != null)
083: utilTimer
084: .timerString(" createModelViewEntity: before general/basic info");
085: this .populateBasicInfo(entityElement, docElement,
086: docElementValues);
087:
088: if (utilTimer != null)
089: utilTimer
090: .timerString(" createModelViewEntity: before \"member-entity\"s");
091: List memberEntityList = UtilXml.childElementList(entityElement,
092: "member-entity");
093: Iterator memberEntityIter = memberEntityList.iterator();
094: while (memberEntityIter.hasNext()) {
095: Element memberEntityElement = (Element) memberEntityIter
096: .next();
097: String alias = UtilXml.checkEmpty(memberEntityElement
098: .getAttribute("entity-alias"));
099: String name = UtilXml.checkEmpty(memberEntityElement
100: .getAttribute("entity-name"));
101: if (name.length() <= 0 || alias.length() <= 0) {
102: Debug
103: .logError(
104: "[new ModelViewEntity] entity-alias or entity-name missing on member-entity element of the view-entity "
105: + this .entityName, module);
106: } else {
107: ModelMemberEntity modelMemberEntity = new ModelMemberEntity(
108: alias, name);
109: this .addMemberModelMemberEntity(modelMemberEntity);
110: }
111: }
112:
113: // when reading aliases and alias-alls, just read them into the alias list, there will be a pass
114: // after loading all entities to go back and fill in all of the ModelField entries
115: List aliasAllList = UtilXml.childElementList(entityElement,
116: "alias-all");
117: Iterator aliasAllIter = aliasAllList.iterator();
118: while (aliasAllIter.hasNext()) {
119: Element aliasElement = (Element) aliasAllIter.next();
120: ModelViewEntity.ModelAliasAll aliasAll = new ModelAliasAll(
121: aliasElement);
122: this .aliasAlls.add(aliasAll);
123: }
124:
125: if (utilTimer != null)
126: utilTimer
127: .timerString(" createModelViewEntity: before aliases");
128: List aliasList = UtilXml.childElementList(entityElement,
129: "alias");
130: Iterator aliasIter = aliasList.iterator();
131: while (aliasIter.hasNext()) {
132: Element aliasElement = (Element) aliasIter.next();
133: ModelViewEntity.ModelAlias alias = new ModelAlias(
134: aliasElement);
135: this .aliases.add(alias);
136: }
137:
138: List viewLinkList = UtilXml.childElementList(entityElement,
139: "view-link");
140: Iterator viewLinkIter = viewLinkList.iterator();
141: while (viewLinkIter.hasNext()) {
142: Element viewLinkElement = (Element) viewLinkIter.next();
143: ModelViewLink viewLink = new ModelViewLink(viewLinkElement);
144: this .addViewLink(viewLink);
145: }
146:
147: if (utilTimer != null)
148: utilTimer
149: .timerString(" createModelEntity: before relations");
150: this .populateRelated(reader, entityElement);
151:
152: // before finishing, make sure the table name is null, this should help bring up errors early...
153: this .tableName = null;
154: }
155:
156: public ModelViewEntity(DynamicViewEntity dynamicViewEntity,
157: ModelReader modelReader) {
158: this .entityName = dynamicViewEntity.getEntityName();
159: this .packageName = dynamicViewEntity.getPackageName();
160: this .title = dynamicViewEntity.getTitle();
161: this .defaultResourceName = dynamicViewEntity
162: .getDefaultResourceName();
163:
164: // member-entities
165: Iterator modelMemberEntitiesEntryIter = dynamicViewEntity
166: .getModelMemberEntitiesEntryIter();
167: while (modelMemberEntitiesEntryIter.hasNext()) {
168: Map.Entry entry = (Map.Entry) modelMemberEntitiesEntryIter
169: .next();
170: this .addMemberModelMemberEntity((ModelMemberEntity) entry
171: .getValue());
172: }
173:
174: // alias-alls
175: dynamicViewEntity.addAllAliasAllsToList(this .aliasAlls);
176:
177: // aliases
178: dynamicViewEntity.addAllAliasesToList(this .aliases);
179:
180: // view-links
181: dynamicViewEntity.addAllViewLinksToList(this .viewLinks);
182:
183: // relations
184: dynamicViewEntity.addAllRelationsToList(this .relations);
185:
186: // finalize stuff
187: this .populateFields(modelReader);
188: }
189:
190: public Map getMemberModelMemberEntities() {
191: return this .memberModelMemberEntities;
192: }
193:
194: public List getAllModelMemberEntities() {
195: return this .allModelMemberEntities;
196: }
197:
198: public ModelMemberEntity getMemberModelMemberEntity(String alias) {
199: return (ModelMemberEntity) this .memberModelMemberEntities
200: .get(alias);
201: }
202:
203: public ModelEntity getMemberModelEntity(String alias) {
204: if (this .memberModelEntities == null) {
205: this .memberModelEntities = new HashMap();
206: populateFields(this .getModelReader());
207: }
208: return (ModelEntity) this .memberModelEntities.get(alias);
209: }
210:
211: public void addMemberModelMemberEntity(
212: ModelMemberEntity modelMemberEntity) {
213: this .memberModelMemberEntities.put(modelMemberEntity
214: .getEntityAlias(), modelMemberEntity);
215: this .allModelMemberEntities.add(modelMemberEntity);
216: }
217:
218: public void removeMemberModelMemberEntity(String alias) {
219: ModelMemberEntity modelMemberEntity = (ModelMemberEntity) this .memberModelMemberEntities
220: .remove(alias);
221:
222: if (modelMemberEntity == null)
223: return;
224: this .allModelMemberEntities.remove(modelMemberEntity);
225: }
226:
227: /** The col-name of the Field, the alias of the field if this is on a view-entity */
228: public String getColNameOrAlias(String fieldName) {
229: ModelField modelField = this .getField(fieldName);
230: String fieldString = modelField.getColName();
231: ModelViewEntity.ModelAlias alias = getAlias(fieldName);
232: if (alias != null) {
233: fieldString = alias.getColAlias();
234: }
235: return fieldString;
236: }
237:
238: /** List of aliases with information in addition to what is in the standard field list */
239: public ModelAlias getAlias(int index) {
240: return (ModelAlias) this .aliases.get(index);
241: }
242:
243: public ModelAlias getAlias(String name) {
244: Iterator aliasIter = getAliasesIterator();
245: while (aliasIter.hasNext()) {
246: ModelAlias alias = (ModelAlias) aliasIter.next();
247: if (alias.name.equals(name)) {
248: return alias;
249: }
250: }
251: return null;
252: }
253:
254: public int getAliasesSize() {
255: return this .aliases.size();
256: }
257:
258: public Iterator getAliasesIterator() {
259: return this .aliases.iterator();
260: }
261:
262: public List getAliasesCopy() {
263: return new ArrayList(this .aliases);
264: }
265:
266: public List getGroupBysCopy() {
267: return new ArrayList(this .groupBys);
268: }
269:
270: /** List of view links to define how entities are connected (or "joined") */
271: public ModelViewLink getViewLink(int index) {
272: return (ModelViewLink) this .viewLinks.get(index);
273: }
274:
275: public int getViewLinksSize() {
276: return this .viewLinks.size();
277: }
278:
279: public Iterator getViewLinksIterator() {
280: return this .viewLinks.iterator();
281: }
282:
283: public List getViewLinksCopy() {
284: return new ArrayList(this .viewLinks);
285: }
286:
287: public void addViewLink(ModelViewLink viewLink) {
288: this .viewLinks.add(viewLink);
289: }
290:
291: public String colNameString(List flds, String separator,
292: String afterLast, boolean alias) {
293: StringBuffer returnString = new StringBuffer();
294:
295: if (flds.size() < 1) {
296: return "";
297: }
298:
299: Iterator fldsIt = flds.iterator();
300: while (fldsIt.hasNext()) {
301: ModelField field = (ModelField) fldsIt.next();
302: returnString.append(field.colName);
303: if (alias) {
304: ModelAlias modelAlias = this .getAlias(field.name);
305: if (modelAlias != null) {
306: returnString.append(" AS " + modelAlias.colAlias);
307: }
308: }
309: if (fldsIt.hasNext()) {
310: returnString.append(separator);
311: }
312: }
313:
314: returnString.append(afterLast);
315: return returnString.toString();
316: }
317:
318: public ModelEntity getAliasedEntity(String entityAlias,
319: ModelReader modelReader) {
320: ModelMemberEntity modelMemberEntity = (ModelMemberEntity) this .memberModelMemberEntities
321: .get(entityAlias);
322: if (modelMemberEntity == null) {
323: Debug.logError("No member entity with alias " + entityAlias
324: + " found in view-entity " + this .getEntityName()
325: + "; this view-entity will NOT be usable...",
326: module);
327: return null;
328: }
329:
330: String aliasedEntityName = modelMemberEntity.getEntityName();
331: ModelEntity aliasedEntity = modelReader
332: .getModelEntityNoCheck(aliasedEntityName);
333: if (aliasedEntity == null) {
334: Debug
335: .logError(
336: "[ModelViewEntity.populateFields] ERROR: could not find ModelEntity for entity name: "
337: + aliasedEntityName, module);
338: return null;
339: }
340:
341: return aliasedEntity;
342: }
343:
344: public ModelField getAliasedField(ModelEntity aliasedEntity,
345: String field, ModelReader modelReader) {
346: ModelField aliasedField = aliasedEntity.getField(field);
347: if (aliasedEntity == null) {
348: Debug
349: .logError(
350: "[ModelViewEntity.populateFields] ERROR: could not find ModelEntity for entity name: "
351: + aliasedEntity.getEntityName(),
352: module);
353: return null;
354: }
355: return aliasedField;
356: }
357:
358: public void populateFields(ModelReader modelReader) {
359: if (this .memberModelEntities == null) {
360: this .memberModelEntities = new HashMap();
361: }
362:
363: Iterator meIter = memberModelMemberEntities.entrySet()
364: .iterator();
365: while (meIter.hasNext()) {
366: Map.Entry entry = (Map.Entry) meIter.next();
367:
368: ModelMemberEntity modelMemberEntity = (ModelMemberEntity) entry
369: .getValue();
370: String aliasedEntityName = modelMemberEntity
371: .getEntityName();
372: ModelEntity aliasedEntity = modelReader
373: .getModelEntityNoCheck(aliasedEntityName);
374: if (aliasedEntity == null) {
375: continue;
376: }
377: memberModelEntities.put(entry.getKey(), aliasedEntity);
378: }
379:
380: expandAllAliasAlls(modelReader);
381:
382: for (int i = 0; i < aliases.size(); i++) {
383: ModelAlias alias = (ModelAlias) aliases.get(i);
384: ModelField field = new ModelField();
385: field.name = alias.name;
386:
387: // if this is a groupBy field, add it to the groupBys list
388: if (alias.groupBy) {
389: this .groupBys.add(field);
390: }
391:
392: // show a warning if function is specified and groupBy is true
393: if (UtilValidate.isNotEmpty(alias.function)
394: && alias.groupBy) {
395: Debug
396: .logWarning(
397: "The view-entity alias with name="
398: + alias.name
399: + " has a function value and is specified as a group-by field; this may be an error, but is not necessarily.",
400: module);
401: }
402:
403: if (alias.isComplexAlias()) {
404: // if this is a complex alias, make a complex column name...
405: StringBuffer colNameBuffer = new StringBuffer();
406: StringBuffer fieldTypeBuffer = new StringBuffer();
407: alias.makeAliasColName(colNameBuffer, fieldTypeBuffer,
408: this , modelReader);
409: field.colName = colNameBuffer.toString();
410: field.type = fieldTypeBuffer.toString();
411: field.isPk = false;
412: } else {
413: ModelEntity aliasedEntity = getAliasedEntity(
414: alias.entityAlias, modelReader);
415: ModelField aliasedField = getAliasedField(
416: aliasedEntity, alias.field, modelReader);
417: if (aliasedField == null) {
418: Debug
419: .logError(
420: "[ModelViewEntity.populateFields] ERROR: could not find ModelField for field name \""
421: + alias.field
422: + "\" on entity with name: "
423: + aliasedEntity
424: .getEntityName(),
425: module);
426: continue;
427: }
428:
429: if (alias.isPk != null) {
430: field.isPk = alias.isPk.booleanValue();
431: } else {
432: field.isPk = aliasedField.isPk;
433: }
434:
435: field.type = aliasedField.type;
436: field.validators = aliasedField.validators;
437:
438: field.colName = alias.entityAlias
439: + "."
440: + SqlJdbcUtil
441: .filterColName(aliasedField.colName);
442: }
443:
444: this .fields.add(field);
445: if (field.isPk) {
446: this .pks.add(field);
447: } else {
448: this .nopks.add(field);
449: }
450:
451: if ("count".equals(alias.function)
452: || "count-distinct".equals(alias.function)) {
453: // if we have a "count" function we have to change the type
454: field.type = "numeric";
455: }
456:
457: if (UtilValidate.isNotEmpty(alias.function)) {
458: String prefix = (String) functionPrefixMap
459: .get(alias.function);
460: if (prefix == null) {
461: Debug
462: .logWarning(
463: "Specified alias function ["
464: + alias.function
465: + "] not valid; must be: min, max, sum, avg, count or count-distinct; using a column name with no function function",
466: module);
467: } else {
468: field.colName = prefix + field.colName + ")";
469: }
470: }
471: }
472: }
473:
474: /**
475: * Go through all aliasAlls and create an alias for each field of each member entity
476: */
477: private void expandAllAliasAlls(ModelReader modelReader) {
478: Iterator aliasAllIter = aliasAlls.iterator();
479: while (aliasAllIter.hasNext()) {
480: ModelAliasAll aliasAll = (ModelAliasAll) aliasAllIter
481: .next();
482: String prefix = aliasAll.getPrefix();
483:
484: ModelMemberEntity modelMemberEntity = (ModelMemberEntity) memberModelMemberEntities
485: .get(aliasAll.getEntityAlias());
486: if (modelMemberEntity == null) {
487: Debug.logError(
488: "Member entity referred to in alias-all not found, ignoring: "
489: + aliasAll.getEntityAlias(), module);
490: continue;
491: }
492:
493: String aliasedEntityName = modelMemberEntity
494: .getEntityName();
495: ModelEntity aliasedEntity = modelReader
496: .getModelEntityNoCheck(aliasedEntityName);
497: if (aliasedEntity == null) {
498: Debug.logError("Entity referred to in member-entity "
499: + aliasAll.getEntityAlias()
500: + " not found, ignoring: " + aliasedEntityName,
501: module);
502: continue;
503: }
504:
505: List entFieldList = aliasedEntity.getAllFieldNames();
506: if (entFieldList == null) {
507: Debug.logError("Entity referred to in member-entity "
508: + aliasAll.getEntityAlias()
509: + " has no fields, ignoring: "
510: + aliasedEntityName, module);
511: continue;
512: }
513:
514: Iterator fieldnamesIterator = entFieldList.iterator();
515: while (fieldnamesIterator.hasNext()) {
516: // now merge the lists, leaving out any that duplicate an existing alias name
517: String fieldName = (String) fieldnamesIterator.next();
518: String aliasName = fieldName;
519: ModelField modelField = aliasedEntity
520: .getField(fieldName);
521: if (modelField.getIsAutoCreatedInternal()) {
522: // never auto-alias these
523: continue;
524: }
525: if (UtilValidate.isNotEmpty(prefix)) {
526: StringBuffer newAliasBuffer = new StringBuffer(
527: prefix);
528: //make sure the first letter is uppercase to delineate the field name
529: newAliasBuffer.append(Character
530: .toUpperCase(aliasName.charAt(0)));
531: newAliasBuffer.append(aliasName.substring(1));
532: aliasName = newAliasBuffer.toString();
533: }
534:
535: ModelAlias existingAlias = this .getAlias(aliasName);
536: if (existingAlias != null) {
537: //log differently if this is part of a view-link key-map because that is a common case when a field will be auto-expanded multiple times
538: boolean isInViewLink = false;
539: Iterator viewLinkIter = this .getViewLinksIterator();
540: while (viewLinkIter.hasNext() && !isInViewLink) {
541: ModelViewLink modelViewLink = (ModelViewLink) viewLinkIter
542: .next();
543: boolean isRel = false;
544: if (modelViewLink.getRelEntityAlias().equals(
545: aliasAll.getEntityAlias())) {
546: isRel = true;
547: } else if (!modelViewLink.getEntityAlias()
548: .equals(aliasAll.getEntityAlias())) {
549: // not the rel-entity-alias or the entity-alias, so move along
550: continue;
551: }
552: Iterator keyMapIter = modelViewLink
553: .getKeyMapsIterator();
554: while (keyMapIter.hasNext() && !isInViewLink) {
555: ModelKeyMap modelKeyMap = (ModelKeyMap) keyMapIter
556: .next();
557: if (!isRel
558: && modelKeyMap.getFieldName()
559: .equals(fieldName)) {
560: isInViewLink = true;
561: } else if (isRel
562: && modelKeyMap.getRelFieldName()
563: .equals(fieldName)) {
564: isInViewLink = true;
565: }
566: }
567: }
568:
569: //already exists, oh well... probably an override, but log just in case
570: String warnMsg = "Throwing out field alias in view entity "
571: + this .getEntityName()
572: + " because one already exists with the name: "
573: + aliasName;
574: if (isInViewLink) {
575: Debug.logVerbose(warnMsg, module);
576: } else {
577: Debug.logInfo(warnMsg, module);
578: }
579: continue;
580: }
581:
582: ModelAlias expandedAlias = new ModelAlias();
583: expandedAlias.name = aliasName;
584: expandedAlias.field = fieldName;
585: expandedAlias.entityAlias = aliasAll.getEntityAlias();
586: expandedAlias.isFromAliasAll = true;
587: expandedAlias.colAlias = ModelUtil
588: .javaNameToDbName(UtilXml
589: .checkEmpty(expandedAlias.name));
590: aliases.add(expandedAlias);
591: }
592: }
593: }
594:
595: public static class ModelMemberEntity {
596: protected String entityAlias = "";
597: protected String entityName = "";
598:
599: public ModelMemberEntity(String entityAlias, String entityName) {
600: this .entityAlias = entityAlias;
601: this .entityName = entityName;
602: }
603:
604: public String getEntityAlias() {
605: return this .entityAlias;
606: }
607:
608: public String getEntityName() {
609: return this .entityName;
610: }
611: }
612:
613: public static class ModelAliasAll {
614: protected String entityAlias = "";
615: protected String prefix = "";
616:
617: protected ModelAliasAll() {
618: }
619:
620: public ModelAliasAll(String entityAlias, String prefix) {
621: this .entityAlias = entityAlias;
622: this .prefix = prefix;
623: }
624:
625: public ModelAliasAll(Element aliasAllElement) {
626: this .entityAlias = UtilXml.checkEmpty(aliasAllElement
627: .getAttribute("entity-alias"));
628: this .prefix = UtilXml.checkEmpty(aliasAllElement
629: .getAttribute("prefix"));
630: }
631:
632: public String getEntityAlias() {
633: return this .entityAlias;
634: }
635:
636: public String getPrefix() {
637: return this .prefix;
638: }
639: }
640:
641: public static class ModelAlias {
642: protected String entityAlias = "";
643: protected String name = "";
644: protected String field = "";
645: protected String colAlias = "";
646: // this is a Boolean object for a tri-state: null, true or false
647: protected Boolean isPk = null;
648: protected boolean groupBy = false;
649: // is specified this alias is a calculated value; can be: min, max, sum, avg, count, count-distinct
650: protected String function = null;
651: protected boolean isFromAliasAll = false;
652: protected ComplexAliasMember complexAliasMember = null;
653:
654: protected ModelAlias() {
655: }
656:
657: public ModelAlias(Element aliasElement) {
658: this .entityAlias = UtilXml.checkEmpty(aliasElement
659: .getAttribute("entity-alias"));
660: this .name = UtilXml.checkEmpty(aliasElement
661: .getAttribute("name"));
662: this .field = UtilXml.checkEmpty(aliasElement
663: .getAttribute("field"), this .name);
664: this .colAlias = UtilXml.checkEmpty(aliasElement
665: .getAttribute("col-alias"), ModelUtil
666: .javaNameToDbName(UtilXml.checkEmpty(this .name)));
667: String primKeyValue = UtilXml.checkEmpty(aliasElement
668: .getAttribute("prim-key"));
669:
670: if (UtilValidate.isNotEmpty(primKeyValue)) {
671: this .isPk = new Boolean("true".equals(primKeyValue));
672: } else {
673: this .isPk = null;
674: }
675: this .groupBy = "true".equals(UtilXml
676: .checkEmpty(aliasElement.getAttribute("group-by")));
677: this .function = UtilXml.checkEmpty(aliasElement
678: .getAttribute("function"));
679:
680: Element complexAliasElement = UtilXml.firstChildElement(
681: aliasElement, "complex-alias");
682: if (complexAliasElement != null) {
683: complexAliasMember = new ComplexAlias(
684: complexAliasElement);
685: }
686: }
687:
688: public ModelAlias(String entityAlias, String name,
689: String field, String colAlias, Boolean isPk,
690: Boolean groupBy, String function) {
691: this .entityAlias = entityAlias;
692: this .name = name;
693: this .field = field;
694: this .colAlias = colAlias;
695: this .field = UtilXml.checkEmpty(field, this .name);
696: this .colAlias = UtilXml.checkEmpty(colAlias, ModelUtil
697: .javaNameToDbName(UtilXml.checkEmpty(this .name)));
698: this .isPk = isPk;
699: if (groupBy != null) {
700: this .groupBy = groupBy.booleanValue();
701: } else {
702: this .groupBy = false;
703: }
704: this .function = function;
705: }
706:
707: public void setComplexAliasMember(
708: ComplexAliasMember complexAliasMember) {
709: this .complexAliasMember = complexAliasMember;
710: }
711:
712: public boolean isComplexAlias() {
713: return complexAliasMember != null;
714: }
715:
716: public void makeAliasColName(StringBuffer colNameBuffer,
717: StringBuffer fieldTypeBuffer,
718: ModelViewEntity modelViewEntity, ModelReader modelReader) {
719: if (complexAliasMember != null) {
720: complexAliasMember.makeAliasColName(colNameBuffer,
721: fieldTypeBuffer, modelViewEntity, modelReader);
722: }
723: }
724:
725: public String getEntityAlias() {
726: return this .entityAlias;
727: }
728:
729: public String getName() {
730: return this .name;
731: }
732:
733: public String getColAlias() {
734: return this .colAlias;
735: }
736:
737: public String getField() {
738: return this .field;
739: }
740:
741: public Boolean getIsPk() {
742: return this .isPk;
743: }
744:
745: public boolean getGroupBy() {
746: return this .groupBy;
747: }
748:
749: public String getFunction() {
750: return this .function;
751: }
752:
753: public boolean getIsFromAliasAll() {
754: return this .isFromAliasAll;
755: }
756: }
757:
758: public static interface ComplexAliasMember {
759: public void makeAliasColName(StringBuffer colNameBuffer,
760: StringBuffer fieldTypeBuffer,
761: ModelViewEntity modelViewEntity, ModelReader modelReader);
762: }
763:
764: public static class ComplexAlias implements ComplexAliasMember {
765: protected List complexAliasMembers = new LinkedList();
766: protected String operator;
767:
768: public ComplexAlias(String operator) {
769: this .operator = operator;
770: }
771:
772: public ComplexAlias(Element complexAliasElement) {
773: this .operator = complexAliasElement
774: .getAttribute("operator");
775: // handle all complex-alias and complex-alias-field sub-elements
776: List subElements = UtilXml.childElementList(
777: complexAliasElement, null);
778: Iterator subElementIter = subElements.iterator();
779: while (subElementIter.hasNext()) {
780: Element subElement = (Element) subElementIter.next();
781: String nodeName = subElement.getNodeName();
782: if ("complex-alias".equals(nodeName)) {
783: this .addComplexAliasMember(new ComplexAlias(
784: subElement));
785: } else if ("complex-alias-field".equals(nodeName)) {
786: this .addComplexAliasMember(new ComplexAliasField(
787: subElement));
788: }
789: }
790: }
791:
792: public void addComplexAliasMember(
793: ComplexAliasMember complexAliasMember) {
794: this .complexAliasMembers.add(complexAliasMember);
795: }
796:
797: public void makeAliasColName(StringBuffer colNameBuffer,
798: StringBuffer fieldTypeBuffer,
799: ModelViewEntity modelViewEntity, ModelReader modelReader) {
800: if (complexAliasMembers.size() == 0) {
801: return;
802: } else if (complexAliasMembers.size() == 1) {
803: ComplexAliasMember complexAliasMember = (ComplexAliasMember) complexAliasMembers
804: .iterator().next();
805: complexAliasMember.makeAliasColName(colNameBuffer,
806: fieldTypeBuffer, modelViewEntity, modelReader);
807: } else {
808: colNameBuffer.append('(');
809: Iterator complexAliasMemberIter = complexAliasMembers
810: .iterator();
811: while (complexAliasMemberIter.hasNext()) {
812: ComplexAliasMember complexAliasMember = (ComplexAliasMember) complexAliasMemberIter
813: .next();
814: complexAliasMember.makeAliasColName(colNameBuffer,
815: fieldTypeBuffer, modelViewEntity,
816: modelReader);
817: if (complexAliasMemberIter.hasNext()) {
818: colNameBuffer.append(' ');
819: colNameBuffer.append(this .operator);
820: colNameBuffer.append(' ');
821: }
822: }
823: colNameBuffer.append(')');
824: }
825: }
826: }
827:
828: public static class ComplexAliasField implements ComplexAliasMember {
829: protected String entityAlias = "";
830: protected String field = "";
831: protected String function = null;
832:
833: public ComplexAliasField(String entityAlias, String field) {
834: this .entityAlias = entityAlias;
835: this .field = field;
836: }
837:
838: public ComplexAliasField(String entityAlias, String field,
839: String function) {
840: this .entityAlias = entityAlias;
841: this .field = field;
842: this .function = function;
843: }
844:
845: public ComplexAliasField(Element complexAliasFieldElement) {
846: this .entityAlias = complexAliasFieldElement
847: .getAttribute("entity-alias");
848: this .field = complexAliasFieldElement.getAttribute("field");
849: this .function = complexAliasFieldElement
850: .getAttribute("function");
851: }
852:
853: public void makeAliasColName(StringBuffer colNameBuffer,
854: StringBuffer fieldTypeBuffer,
855: ModelViewEntity modelViewEntity, ModelReader modelReader) {
856: ModelEntity modelEntity = modelViewEntity.getAliasedEntity(
857: entityAlias, modelReader);
858: ModelField modelField = modelViewEntity.getAliasedField(
859: modelEntity, field, modelReader);
860:
861: String colName = entityAlias + "."
862: + modelField.getColName();
863:
864: if (UtilValidate.isNotEmpty(function)) {
865: String prefix = (String) functionPrefixMap
866: .get(function);
867: if (prefix == null) {
868: Debug
869: .logWarning(
870: "Specified alias function ["
871: + function
872: + "] not valid; must be: min, max, sum, avg, count or count-distinct; using a column name with no function function",
873: module);
874: } else {
875: colName = prefix + colName + ")";
876: }
877: }
878:
879: colNameBuffer.append(colName);
880:
881: //set fieldTypeBuffer if not already set
882: if (fieldTypeBuffer.length() == 0) {
883: fieldTypeBuffer.append(modelField.type);
884: }
885: }
886: }
887:
888: public static class ModelViewLink {
889: protected String entityAlias = "";
890: protected String relEntityAlias = "";
891: protected boolean relOptional = false;
892: protected List keyMaps = new ArrayList();
893:
894: protected ModelViewLink() {
895: }
896:
897: public ModelViewLink(Element viewLinkElement) {
898: this .entityAlias = UtilXml.checkEmpty(viewLinkElement
899: .getAttribute("entity-alias"));
900: this .relEntityAlias = UtilXml.checkEmpty(viewLinkElement
901: .getAttribute("rel-entity-alias"));
902: // if anything but true will be false; ie defaults to false
903: this .relOptional = "true".equals(viewLinkElement
904: .getAttribute("rel-optional"));
905:
906: NodeList keyMapList = viewLinkElement
907: .getElementsByTagName("key-map");
908: for (int j = 0; j < keyMapList.getLength(); j++) {
909: Element keyMapElement = (Element) keyMapList.item(j);
910: ModelKeyMap keyMap = new ModelKeyMap(keyMapElement);
911:
912: if (keyMap != null)
913: keyMaps.add(keyMap);
914: }
915: }
916:
917: public ModelViewLink(String entityAlias, String relEntityAlias,
918: Boolean relOptional, List keyMaps) {
919: this .entityAlias = entityAlias;
920: this .relEntityAlias = relEntityAlias;
921: if (relOptional != null) {
922: this .relOptional = relOptional.booleanValue();
923: }
924: this .keyMaps.addAll(keyMaps);
925: }
926:
927: public String getEntityAlias() {
928: return this .entityAlias;
929: }
930:
931: public String getRelEntityAlias() {
932: return this .relEntityAlias;
933: }
934:
935: public boolean isRelOptional() {
936: return this .relOptional;
937: }
938:
939: public ModelKeyMap getKeyMap(int index) {
940: return (ModelKeyMap) this .keyMaps.get(index);
941: }
942:
943: public int getKeyMapsSize() {
944: return this .keyMaps.size();
945: }
946:
947: public Iterator getKeyMapsIterator() {
948: return this .keyMaps.iterator();
949: }
950:
951: public List getKeyMapsCopy() {
952: return new ArrayList(this.keyMaps);
953: }
954: }
955: }
|