View Javadoc

1   /*
2    * Copyright 2004-2006 the Seasar Foundation and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.seasar.tuigwaa.controller;
17  
18  import java.util.ArrayList;
19  import java.util.HashMap;
20  import java.util.HashSet;
21  import java.util.Iterator;
22  import java.util.List;
23  import java.util.Map;
24  import java.util.Set;
25  import java.util.TreeSet;
26  
27  import javax.servlet.http.HttpServletRequest;
28  
29  import org.apache.commons.lang.StringUtils;
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.apache.commons.validator.GenericValidator;
33  import org.apache.ecs.html.BR;
34  import org.apache.ecs.html.Div;
35  import org.apache.ecs.html.Input;
36  import org.apache.ecs.html.Span;
37  import org.apache.struts.action.ActionErrors;
38  import org.apache.struts.action.ActionMapping;
39  import org.apache.struts.action.ActionMessage;
40  import org.seasar.tuigwaa.controller.config.ValidatorUtils;
41  import org.seasar.tuigwaa.database.function.CriteriaExeFunction;
42  import org.seasar.tuigwaa.model.ModelService;
43  import org.seasar.tuigwaa.model.common.EntityInfo;
44  import org.seasar.tuigwaa.model.common.EntityUtils;
45  import org.seasar.tuigwaa.model.common.TgwAttributeVisitor;
46  import org.seasar.tuigwaa.model.core.TgwAttribute;
47  import org.seasar.tuigwaa.model.core.TgwEntity;
48  import org.seasar.tuigwaa.model.core.impl.BooleanAttribute;
49  import org.seasar.tuigwaa.model.core.impl.DateAttribute;
50  import org.seasar.tuigwaa.model.core.impl.DoubleAttribute;
51  import org.seasar.tuigwaa.model.core.impl.FileAttribute;
52  import org.seasar.tuigwaa.model.core.impl.FkAttribute;
53  import org.seasar.tuigwaa.model.core.impl.FloatAttribute;
54  import org.seasar.tuigwaa.model.core.impl.IntegerAttribute;
55  import org.seasar.tuigwaa.model.core.impl.LongAttribute;
56  import org.seasar.tuigwaa.model.core.impl.SecurityAttribute;
57  import org.seasar.tuigwaa.model.core.impl.SelfAttribute;
58  import org.seasar.tuigwaa.model.core.impl.SetAttribute;
59  import org.seasar.tuigwaa.model.core.impl.StringAttribute;
60  import org.seasar.tuigwaa.model.core.impl.TgwEntityImpl;
61  import org.seasar.tuigwaa.model.core.impl.TimestampAttribute;
62  import org.seasar.tuigwaa.system.Constants;
63  import org.seasar.tuigwaa.util.ActionErrorsSet;
64  import org.seasar.tuigwaa.util.TgwNameUtils;
65  import org.seasar.tuigwaa.util.TgwResource;
66  import org.seasar.tuigwaa.util.ajax.AbstractRowSetForm;
67  
68  import com.isenshi.util.HtmlBuffer;
69  import com.isenshi.util.UniqueNameGenerator;
70  
71  /***
72   * テーブルを作成するフォームに対応
73   * 
74   * @author nishioka
75   */
76  public class EntityForm extends AbstractRowSetForm {
77  	private static final long serialVersionUID = -655809929347851397L;
78  
79  	public static final int FORM_REPRE = 0;
80  
81  	public static final int FORM_TYPE = 1;
82  
83  	public static final int FORM_DISPLAYNAME = 2;
84  
85  	public static final int FORM_COLUMNNAME = 3;
86  
87  	public static final int FORM_DESCRIPTION = 4;
88  
89  	public static final int FORM_BASICVALIDATOR = 5;
90  
91  	public static final int FORM_EXTRAFORM = 6;
92  
93  	public static final int FORM_ACTION = 7;
94  
95  	public static final int[] FORMS = { FORM_REPRE, FORM_TYPE,
96  			FORM_DISPLAYNAME, FORM_COLUMNNAME, FORM_DESCRIPTION,
97  			FORM_BASICVALIDATOR, FORM_EXTRAFORM, FORM_ACTION };
98  
99  	private Log log = LogFactory.getLog(getClass());
100 
101 	/***
102 	 * 表示名
103 	 */
104 	private String displayName_;
105 
106 	/***
107 	 * 実テーブル名
108 	 */
109 	private String tableName;
110 
111 	/***
112 	 * 説明
113 	 */
114 	private String description;
115 
116 	/***
117 	 * 主キー(ID)の表示名
118 	 */
119 	private String pkDisplayName;
120 
121 	private boolean isSaved_ = false;
122 
123 	private TgwEntity entity_;
124 
125 	private ModelService entityService_;
126 
127 	private int representative_;
128 
129 	private boolean creationUserFlag;
130 
131 	private boolean modificationUserFlag;
132 
133 	private String creationUserAttrName = TgwResource
134 			.getMessage(EntityUtils.ENTITY_BUILTIN_RESOURCE_PREFIX
135 					+ Constants.ENTITY_BUILTIN_CREATIONUSER);
136 
137 	private String modificationUserAttrName = TgwResource
138 			.getMessage(EntityUtils.ENTITY_BUILTIN_RESOURCE_PREFIX
139 					+ Constants.ENTITY_BUILTIN_MODIFICATIONUSER);
140 
141 	private String creationDateAttrName = TgwResource
142 			.getMessage(EntityUtils.ENTITY_BUILTIN_RESOURCE_PREFIX
143 					+ Constants.ENTITY_BUILTIN_CREATIONDATE);
144 
145 	private String modificationDateAttrName = TgwResource
146 			.getMessage(EntityUtils.ENTITY_BUILTIN_RESOURCE_PREFIX
147 					+ Constants.ENTITY_BUILTIN_MODIFICATIONDATE);
148 
149 	private boolean userUnique;
150 
151 	private boolean lastCreationUserFlag;
152 
153 	private boolean lastModificationUserFlag;
154 
155 	private boolean lastUserUniqueFlag;
156 
157 	private boolean creationFieldFlag;
158 
159 	private boolean modificationFieldFlag;
160 
161 	private boolean lastModificationFieldFlag;
162 
163 	private boolean lastCreationFieldFlag;
164 
165 	private List additionalEntities;
166 
167 	private boolean randomId;
168 
169 	private boolean easyMode;
170 
171 	private UniqueNameGenerator attrNameGenerator = new UniqueNameGenerator();
172 
173 	private UniqueNameGenerator m2mNameGenerator = new UniqueNameGenerator();
174 
175 	private Map m2mRefEntityMap = new HashMap();
176 
177 	private List removedAttrNames = new ArrayList();
178 
179 	public EntityForm(String schema, boolean easyMode,
180 			ModelService entityService) {
181 		init(new TgwEntityImpl(schema), easyMode, entityService, false);
182 	}
183 
184 	public EntityForm(TgwEntity entity, boolean easyMode,
185 			ModelService entitySerivce) {
186 		init(entity, easyMode, entitySerivce, true);
187 	}
188 
189 	private void init(TgwEntity entity, boolean easyMode,
190 			ModelService entityService, boolean isSaved) {
191 		this.easyMode = easyMode;
192 		this.entity_ = entity;
193 		this.entityService_ = entityService;
194 		this.isSaved_ = isSaved;
195 		if (isSaved) {
196 			setSavedEntity(entity);
197 		} else {
198 			// 新規テーブル作成時に
199 			// 最初から1つカラムを作成しておく
200 			super.addRow(createNewRow());
201 			// 主キー(ID)の表示名のデフォルト値を設定しておく
202 			setPkDisplayName(entity.getPrimaryKeyDisplayName());
203 		}
204 	}
205 
206 	public ActionErrors validate(ActionMapping mapping,
207 			HttpServletRequest request) {
208 
209 		ActionErrors errors = new ActionErrorsSet();
210 		errors.add(super.validate(mapping, request));
211 
212 		if (!easyMode && (tableName == null || tableName.length() == 0)) {
213 			errors.add("tableName", new ActionMessage("errors.required",
214 					TgwResource.getMessage("form.entityForm.tableName")));
215 		}
216 
217 		List list = getRowSet();
218 
219 		if (list.size() == 0) {
220 			errors.add("column", new ActionMessage("error.message.zerorow"));
221 			return errors;
222 		}
223 
224 		Set columnNameSet = new TreeSet();
225 		for (int i = 0; i < list.size(); i++) {
226 			TgwAttribute field = (TgwAttribute) list.get(i);
227 			field.accept(new ValidationVisitor(errors, i), null);
228 
229 			if (!easyMode) { // 標準編集モードのときのみの入力チェック
230 				String name = field.getName();
231 				if (!GenericValidator.isBlankOrNull(name)
232 						&& columnNameSet.contains(name)) {
233 					ActionMessage message = new ActionMessage(
234 							"errors.duplicated", TgwResource
235 									.getMessage("form.entityForm.columnName"));
236 					errors.add("column", message);
237 				}
238 				columnNameSet.add(name);
239 			}
240 		}
241 
242 		return errors;
243 	}
244 
245 	public void reset(ActionMapping actionMapping, HttpServletRequest request) {
246 		this.lastCreationUserFlag = creationUserFlag;
247 		this.lastModificationUserFlag = modificationUserFlag;
248 		this.lastCreationFieldFlag = creationFieldFlag;
249 		this.lastModificationFieldFlag = modificationFieldFlag;
250 		this.lastUserUniqueFlag = isUserUnique();
251 
252 		this.creationUserFlag = false;
253 		this.modificationUserFlag = false;
254 		this.creationFieldFlag = false;
255 		this.modificationFieldFlag = false;
256 		this.userUnique = false;
257 
258 		this.randomId = false;
259 
260 		for (Iterator i = getRowSet().iterator(); i.hasNext();) {
261 			TgwAttribute attr = (TgwAttribute) i.next();
262 			attr.setRequired(false);
263 		}
264 	}
265 
266 	// ----- Ajax Method -----
267 
268 	protected void removeRow(int index, Object row) {
269 		if (isSaved()) {
270 			TgwAttribute attr = (TgwAttribute) row;
271 			String attrName = attr.getName();
272 
273 			if (attrName != null && attrName.length() > 0) {
274 				removedAttrNames.add(attrName);
275 			}
276 
277 			// TODO The following code should be in the "createEntity" method,
278 			// because reference is collapsed before server synchnronization.
279 			if (row instanceof FkAttribute) {
280 				FkAttribute fk = (FkAttribute) row;
281 				// 一時的な回避策。
282 				// 既に存在する関連データ型カラムである場合にのみ実行
283 				if (fk.getRefEntity() != null) {
284 					fk.getRefEntity().removeReferencedFkField(fk);
285 				}
286 			}
287 		}
288 	}
289 
290 	public String checkIsEntityByAjax(String name) {
291 		log.info("[Ajax:check is entity " + name);
292 		try {
293 			TgwEntity entity = entityService_.getEntity(
294 					entity_.getDomainName(), name);
295 			if (entity == null) {
296 				return "";
297 			} else {
298 				return getMessage("msg.entity.duplicate");
299 			}
300 		} catch (Exception e) {
301 			e.printStackTrace();
302 			throw new RuntimeException(e);
303 		}
304 	}
305 
306 	protected Object createRow(int index, String value) {
307 
308 		String type = value;
309 		String option = null;
310 		int optionIndex = type.indexOf("?");
311 		if (optionIndex > 0) {
312 			option = type.substring(optionIndex + 1, type.length());
313 			type = type.substring(0, optionIndex);
314 		}
315 
316 		TgwAttribute attr = EntityUtils.createAttribute(type);
317 
318 		attr.setEntity(entity_);
319 		attr.setOption(option);
320 		return attr;
321 	}
322 
323 	protected Object createNewRow() {
324 		StringAttribute field = new StringAttribute();
325 		// field.setRequired(true);
326 		return field;
327 	}
328 
329 	protected String[] getHtmlData(int index, Object row) {
330 		String[] htmls = getFormHtml((TgwAttribute) row, getPrefix(index),
331 				index);
332 		return htmls;
333 	}
334 
335 	// [End]----- Ajax Method -----
336 
337 	// [Start] ----- Setter Getter Method -----
338 
339 	public boolean isRandomId() {
340 		return randomId;
341 	}
342 
343 	public void setRandomId(boolean randomId) {
344 		this.randomId = randomId;
345 	}
346 
347 	public boolean isEasyMode() {
348 		return easyMode;
349 	}
350 
351 	public boolean isCreationUserFlag() {
352 		return creationUserFlag;
353 	}
354 
355 	public void setCreationUserFlag(boolean creationUserFlag) {
356 		this.creationUserFlag = creationUserFlag;
357 	}
358 
359 	public boolean isUserUnique() {
360 		return creationUserFlag && userUnique;
361 	}
362 
363 	public void setUserUnique(boolean userUnique) {
364 		this.userUnique = userUnique;
365 	}
366 
367 	public boolean isModificationUserFlag() {
368 		return modificationUserFlag;
369 	}
370 
371 	public void setModificationUserFlag(boolean modificationUserFlag) {
372 		this.modificationUserFlag = modificationUserFlag;
373 	}
374 
375 	public boolean isCreationFieldFlag() {
376 		return creationFieldFlag;
377 	}
378 
379 	public void setCreationFieldFlag(boolean creationFieldFlag) {
380 		this.creationFieldFlag = creationFieldFlag;
381 	}
382 
383 	public boolean isModificationFieldFlag() {
384 		return modificationFieldFlag;
385 	}
386 
387 	public void setModificationFieldFlag(boolean modificationFieldFlag) {
388 		this.modificationFieldFlag = modificationFieldFlag;
389 	}
390 
391 	public TgwEntity getEntity() {
392 		return entity_;
393 	}
394 
395 	public void setRepresentative(int representative) {
396 		this.representative_ = representative;
397 	}
398 
399 	public int getRepresentative() {
400 		return representative_;
401 	}
402 
403 	public boolean isSaved() {
404 		return isSaved_;
405 	}
406 
407 	public String getTableName() {
408 		return tableName;
409 	}
410 
411 	public void setTableName(String tableName) {
412 		this.tableName = tableName;
413 	}
414 
415 	public String getDescription() {
416 		return description;
417 	}
418 
419 	public void setDescription(String description) {
420 		this.description = description;
421 	}
422 
423 	public String getDisplayName() {
424 		return displayName_;
425 	}
426 
427 	public void setDisplayName(String displayName) {
428 		this.displayName_ = displayName;
429 	}
430 
431 	/***
432 	 * 主キー(ID)の表示名を取得する
433 	 */
434 	public String getPkDisplayName() {
435 		return pkDisplayName;
436 	}
437 
438 	/***
439 	 * 主キー(ID)の表示名を設定する
440 	 */
441 	public void setPkDisplayName(String pkDisplayName) {
442 		this.pkDisplayName = pkDisplayName;
443 	}
444 
445 	public String getCreationDateAttrName() {
446 		return creationDateAttrName;
447 	}
448 
449 	public String getCreationUserAttrName() {
450 		return creationUserAttrName;
451 	}
452 
453 	public String getModificationDateAttrName() {
454 		return modificationDateAttrName;
455 	}
456 
457 	public String getModificationUserAttrName() {
458 		return modificationUserAttrName;
459 	}
460 
461 	public void setCreationDateAttrName(String creationDateAttrName) {
462 		this.creationDateAttrName = creationDateAttrName;
463 	}
464 
465 	public void setCreationUserAttrName(String creationUserAttrName) {
466 		this.creationUserAttrName = creationUserAttrName;
467 	}
468 
469 	public void setModificationDateAttrName(String modificationDateAttrName) {
470 		this.modificationDateAttrName = modificationDateAttrName;
471 	}
472 
473 	public void setModificationUserAttrName(String modificationUserAttName) {
474 		this.modificationUserAttrName = modificationUserAttName;
475 	}
476 
477 	private void setManyToManyAttribute(SetAttribute setAttr) {
478 		TgwEntity refEntity = (TgwEntity) m2mRefEntityMap
479 				.get(setAttr.getName());
480 		if (refEntity != null) {
481 			setAttr.setRefEntity(refEntity);
482 			StringAttribute stringattr = (StringAttribute) refEntity
483 					.getField(setAttr.getName());
484 			stringattr.setRestrictions(setAttr.getRestrictions());
485 		} else {
486 			String entityName = setAttr.getEntity().getName();
487 			String refName = TgwNameUtils.toManyToManyName(entityName);
488 			refName = m2mNameGenerator.nextUniqueName(refName);
489 
490 			refEntity = new TgwEntityImpl(entity_.getDomainName(), refName);
491 			refEntity.setHidden(true);
492 			StringAttribute stringAttr = new StringAttribute();
493 			stringAttr.setName(setAttr.getName());
494 			stringAttr.setDisplayName(setAttr.getDisplayName());
495 			stringAttr.setOption(StringAttribute.OPTION_RESTRICTION);
496 			stringAttr.setRestrictions(setAttr.getRestrictions());
497 			refEntity.addField(stringAttr);
498 
499 			FkAttribute fkAttr = new FkAttribute();
500 			String fkname = "tgw_" + setAttr.getName();
501 			fkAttr.setName(fkname);
502 			fkAttr.setDisplayName(" ");
503 			fkAttr.setRefEntity(entity_);
504 			refEntity.addField(fkAttr);
505 
506 			setAttr.setInverseField(fkAttr);
507 			setAttr.setRefEntity(refEntity);
508 			putAdditionalEntity(refEntity);
509 		}
510 	}
511 
512 	public void putAdditionalEntity(TgwEntity additionalEntity) {
513 		if (additionalEntities == null) {
514 			additionalEntities = new ArrayList();
515 		}
516 		additionalEntities.add(additionalEntity);
517 	}
518 
519 	public List getAdditionalEntity() {
520 		return additionalEntities;
521 	}
522 
523 	// [End] ----- Setter Getter Method -----
524 
525 	/***
526 	 * This function is called by EntityAction.
527 	 */
528 	public TgwEntity createEntity() {
529 
530 		if (easyMode && !isSaved_) {
531 			String nextEntityName = entityService_.nextEntityName(entity_
532 					.getDomainName());
533 			entity_.setName(nextEntityName);
534 		} else {
535 			entity_.setName(getTableName());
536 		}
537 
538 		entity_.setDescription(getDescription());
539 		entity_.setDisplayName(getDisplayName());
540 
541 		entity_.setPrimaryKeyDisplayName(getPkDisplayName());
542 		entity_.setRandomId(isRandomId());
543 		entity_.resetAttributes();
544 
545 		for (Iterator i = getRowSet().iterator(); i.hasNext();) {
546 			TgwAttribute attr = (TgwAttribute) i.next();
547 			String attrName = attr.getName();
548 			if (easyMode && (attrName == null || attrName.length() == 0)) {
549 				attr.setName(attrNameGenerator.nextUniqueName("tgw_attr"));
550 			}
551 			if (EntityUtils.isM2MAttribute(attr)) {
552 				setManyToManyAttribute((SetAttribute) attr);
553 			}
554 			entity_.addField(attr);
555 		}
556 
557 		TgwAttribute field = (TgwAttribute) getRowSet()
558 				.get(getRepresentative());
559 		entity_.setRepresentativeField(field.getName());
560 
561 		for (Iterator i = removedAttrNames.iterator(); i.hasNext();) {
562 			String removedAttrName = (String) i.next();
563 			entity_.addRemovedAttrName(removedAttrName);
564 		}
565 
566 		addBuiltinAttribute();
567 
568 		return entity_;
569 	}
570 
571 	// [Start] ------ Private Method ------
572 
573 	private void addBuiltinAttribute() {
574 		if (isCreationUserFlag()) {
575 			EntityUtils.addCreationUserAttribute(entity_, isUserUnique(),
576 					getCreationUserAttrName());
577 		}
578 		if (isModificationUserFlag()) {
579 			EntityUtils.addModificationUserAttribute(entity_,
580 					getModificationUserAttrName());
581 		}
582 		if (isCreationFieldFlag()) {
583 			EntityUtils.addCreationDateAttribute(entity_,
584 					getCreationDateAttrName());
585 		}
586 		if (isModificationFieldFlag()) {
587 			EntityUtils.addModificationDateAttribute(entity_,
588 					getModificationDateAttrName());
589 		}
590 
591 		if ((creationUserFlag != lastCreationUserFlag)
592 				|| (modificationUserFlag != lastModificationUserFlag)
593 				|| (modificationFieldFlag != lastModificationFieldFlag)
594 				|| (creationFieldFlag != lastCreationFieldFlag)
595 				|| (isUserUnique() != lastUserUniqueFlag)) {
596 			setChangedRowElement(true);
597 		}
598 	}
599 
600 	/***
601 	 * カラムのフォームで、エラーが発生した箇所を管理するSet
602 	 */
603 	private HashSet errorPosition = new HashSet();
604 
605 	/***
606 	 * カラムの情報を入力するフォームを返す
607 	 * 
608 	 * @param field
609 	 * @param prefix
610 	 * @param index
611 	 * @return
612 	 */
613 	public String[] getFormHtml(TgwAttribute field, String prefix, int index) {
614 
615 		int length = EntityForm.FORMS.length;
616 		if (easyMode) {
617 			length -= 2;
618 		}
619 		String[] elems = new String[length];
620 
621 		boolean representativeFlag = getRowSet().size() == 1;
622 
623 		int easyModeAdjust = 0;
624 
625 		if (easyMode) {
626 			easyModeAdjust++;
627 		} else {
628 			elems[FORM_REPRE] = getRadioButton(index, representativeFlag);
629 		}
630 
631 		elems[FORM_TYPE - easyModeAdjust] = getTypeSelectHtml(field, prefix,
632 				index);
633 
634 		Input input = new Input(Input.TEXT, prefix + "displayName");
635 		if (field.getDisplayName() != null) {
636 			input.setValue(field.getDisplayName());
637 		}
638 		input.setSize(20);
639 		if (errorPosition.contains(index + "-" + FORM_DISPLAYNAME)) {
640 			input.setClass("errorfield");
641 		}
642 		elems[FORM_DISPLAYNAME - easyModeAdjust] = input.toString();
643 
644 		if (easyMode) {
645 			easyModeAdjust++;
646 		} else {
647 			if (field.getName() == null || !isSaved()) {
648 				input = new Input(Input.TEXT, prefix + "name");
649 				if (field.getName() != null) {
650 					input.setValue(field.getName());
651 				}
652 				if (errorPosition.contains(index + "-" + FORM_COLUMNNAME)) {
653 					input.setClass("errorfield");
654 				}
655 				elems[FORM_COLUMNNAME] = input.toString();
656 			} else {
657 				elems[FORM_COLUMNNAME] = field.getName();
658 			}
659 		}
660 
661 		elems[FORM_DESCRIPTION - easyModeAdjust] = createTextArea(prefix
662 				+ "description", field.getDescription());
663 
664 		elems[FORM_BASICVALIDATOR - easyModeAdjust] = getRequiredHtml(prefix,
665 				index, field.isRequired());
666 
667 		elems[FORM_EXTRAFORM - easyModeAdjust] = (String) field.accept(
668 				new ExtraFormVisitor(prefix, index), null);
669 
670 		elems[FORM_ACTION - easyModeAdjust] = createRemoveButtonHtml(index,
671 				getMessage("button.remove"));
672 
673 		return elems;
674 	}
675 
676 	private String getRadioButton(int index, boolean flag) {
677 		HtmlBuffer buf = new HtmlBuffer();
678 		buf.appendRadio("representative", "" + index, flag);
679 		return buf.toString();
680 	}
681 
682 	private String getRequiredHtml(String prefix, int index, boolean isRequired) {
683 		HtmlBuffer buf = new HtmlBuffer();
684 		buf.appendCheckBox(prefix + "required", isRequired);
685 		return buf.toString();
686 	}
687 
688 	private String getTypeSelectHtml(TgwAttribute field, String prefix,
689 			int index) {
690 		String type = field.getType();
691 		String option = field.getOption();
692 		if (option != null && !option.equals("")) {
693 			type += "?" + option;
694 		}
695 
696 		HtmlBuffer buf = new HtmlBuffer();
697 		buf.appendStartTag(HtmlBuffer.TAG_SLECT);
698 		buf.appendAttribute("name", prefix + "type");
699 		bindTypeEvent(buf);
700 
701 		String[] types = TgwResource.getMessage("field.type.labels").split(",");
702 		for (int i = 0; i < types.length; i++) {
703 			if (types[i].equals(TgwAttribute.TYPE_FK)
704 					&& entityService_.getNewRefList(entity_).size() == 0) {
705 				continue;
706 			} else if (types[i].equals(TgwAttribute.TYPE_SET)
707 					&& entity_.getReferencedFkFieldList().size() == 0) {
708 				continue;
709 			}
710 
711 			String label = getMessage("field.type." + types[i]);
712 			buf.appendOption(label, types[i], type);
713 		}
714 
715 		buf.endTag();
716 		return buf.toString();
717 	}
718 
719 	private void setSavedEntity(TgwEntity entity) {
720 		this.displayName_ = entity.getDisplayName();
721 		this.tableName = entity.getName();
722 		this.description = entity.getDescription();
723 		this.pkDisplayName = entity.getPrimaryKeyDisplayName();
724 		this.randomId = entity.isRandomId();
725 		Iterator itr = entity.getFieldIterator();
726 		while (itr.hasNext()) {
727 			TgwAttribute field = (TgwAttribute) itr.next();
728 			if (EntityUtils.isBuiltinAttribute(field)) {
729 				if (Constants.ENTITY_BUILTIN_CREATIONUSER.equals(field
730 						.getName())) {
731 					setCreationUserAttrName(field.getDisplayName());
732 					setCreationUserFlag(true);
733 				} else if (Constants.ENTITY_BUILTIN_MODIFICATIONUSER
734 						.equals(field.getName())) {
735 					setModificationUserAttrName(field.getDisplayName());
736 					setModificationUserFlag(true);
737 				} else if (Constants.ENTITY_BUILTIN_CREATIONDATE.equals(field
738 						.getName())) {
739 					setCreationDateAttrName(field.getDisplayName());
740 					setCreationFieldFlag(true);
741 				} else if (Constants.ENTITY_BUILTIN_MODIFICATIONDATE
742 						.equals(field.getName())) {
743 					setModificationDateAttrName(field.getDisplayName());
744 					setModificationFieldFlag(true);
745 				}
746 			} else {
747 				if (EntityUtils.isM2MAttribute(field)) {
748 					TgwEntity refEntity = ((SetAttribute) field).getRefEntity();
749 					m2mRefEntityMap.put(field.getName(), refEntity);
750 					m2mNameGenerator.putName(refEntity.getName());
751 				}
752 				attrNameGenerator.putName(field.getName());
753 				super.addRow(field);
754 			}
755 		}
756 		for (Iterator i = entity.getRemovedAttrNames().iterator(); i.hasNext();) {
757 			String removedAttrName = (String) i.next();
758 			attrNameGenerator.putName(removedAttrName);
759 		}
760 	}
761 
762 	// [End] ------ Private Method ------
763 
764 	public class ExtraFormVisitor implements TgwAttributeVisitor {
765 
766 		private String prefix_;
767 
768 		private int index_;
769 
770 		public ExtraFormVisitor(String prefix, int index) {
771 			this.prefix_ = prefix;
772 			this.index_ = index;
773 		}
774 
775 		public Object visit(StringAttribute attr, Object data) {
776 			HtmlBuffer buf = new HtmlBuffer();
777 			if (StringAttribute.OPTION_RESTRICTION.equals(attr.getOption())) {
778 				bindStringRectriction(buf, attr);
779 			} else {
780 				bindSelect(buf, prefix_ + "mask", StringAttribute.MASKS,
781 						"stringfield.mask.", attr.getMask());
782 				buf.appendBr();
783 
784 				String value = "";
785 				if (attr.getLength() > 0) {
786 					value = attr.getLength() + "";
787 				}
788 				buf
789 						.appendBody(getMessage("form.entityForm.column.string.option.maxlength"));
790 				buf.appendTextField(prefix_ + "length", value, 4);
791 			}
792 			return buf.toString();
793 		}
794 
795 		public Object visit(LongAttribute attr, Object data) {
796 			return null;
797 		}
798 
799 		public Object visit(IntegerAttribute attr, Object data) {
800 			if ("restriction".equals(attr.getOption())) {
801 				HtmlBuffer buf = new HtmlBuffer();
802 				buf.appendTextField(prefix_ + "min", "", 8);
803 				buf.appendBody(getMessage("label.from"));
804 				buf.appendTextField(prefix_ + "max", "", 8);
805 				buf.appendBody(getMessage("label.to"));
806 				buf.appendBr();
807 				buf.appendBody(getMessage("label.interval") + ":");
808 				buf.appendTextField(prefix_ + "interval", "", 8);
809 				return buf.toString();
810 			} else {
811 				return "&nbsp;";
812 			}
813 		}
814 
815 		public Object visit(FloatAttribute field, Object data) {
816 			return "&nbsp;";
817 		}
818 
819 		public Object visit(SelfAttribute field, Object data) {
820 			String refEntityFilter = field.getRefEntityFilter();
821 
822 			HtmlBuffer buf = new HtmlBuffer();
823 			if (isSaved_) {
824 				buf.appendStartTag("select");
825 				buf.appendAttribute("name", prefix_ + "refEntityFilter");
826 				buf.appendOption("-", "");
827 				EntityInfo info = entityService_.createEntityInfo(entity_
828 						.getDomainName(), field.getEntity().getName());
829 				for (Iterator fItr = info.getDataFilterList().iterator(); fItr
830 						.hasNext();) {
831 					CriteriaExeFunction exe = (CriteriaExeFunction) fItr.next();
832 					buf.appendOption(exe.getName(), exe.getName(),
833 							refEntityFilter);
834 				}
835 				buf.endTag();
836 			}
837 			return buf.toString();
838 		}
839 
840 		public Object visit(DoubleAttribute field, Object data) {
841 			return "&nbsp;";
842 		}
843 
844 		public Object visit(BooleanAttribute field, Object data) {
845 			HtmlBuffer buf = new HtmlBuffer();
846 
847 			String formType = field.getFormType();
848 			boolean radioSelected = StringAttribute.FORM_RADIO.equals(formType);
849 			buf.appendRadio(prefix_ + "formType", StringAttribute.FORM_RADIO,
850 					radioSelected);
851 			buf.appendBody(getMessage("stringfield.formtype.radio"));
852 
853 			buf.appendRadio(prefix_ + "formType",
854 					StringAttribute.FORM_CHECKBOX, !radioSelected);
855 			buf.appendBody(getMessage("stringfield.formtype.check"));
856 			buf.appendBr();
857 
858 			buf.appendBody("1.");
859 			buf.appendTextField(prefix_ + "trueStr", field.getTrueStr(), 10);
860 			buf.appendBody("2.");
861 			buf.appendTextField(prefix_ + "falseStr", field.getFalseStr(), 10);
862 			return buf.toString();
863 		}
864 
865 		public Object visit(DateAttribute field, Object data) {
866 			HtmlBuffer buf = new HtmlBuffer();
867 
868 			int startYear = field.getStartYear();
869 			int endYear = field.getEndYear();
870 
871 			String startYearLabel = "";
872 			if (startYear > 0) {
873 				startYearLabel = "" + startYear;
874 			}
875 			String endYearLabel = "";
876 			if (startYear > 0) {
877 				endYearLabel = "" + endYear;
878 			}
879 
880 			String lPrefix = "datefield.suffix.";
881 
882 			buf.appendTextField(prefix_ + "startYear", startYearLabel, 4);
883 			bindSelect(buf, prefix_ + "startSuffix", DateAttribute.SUFFIXES,
884 					lPrefix, field.getStartSuffix());
885 			buf.appendBody(getMessage("label.from"));
886 			buf.appendBr();
887 			buf.appendTextField(prefix_ + "endYear", endYearLabel, 4);
888 			bindSelect(buf, prefix_ + "endSuffix", DateAttribute.SUFFIXES,
889 					lPrefix, field.getEndSuffix());
890 			buf.appendBody(getMessage("label.to"));
891 
892 			return buf.toString();
893 		}
894 
895 		public Object visit(FileAttribute field, Object data) {
896 			return "&nbsp;";
897 		}
898 
899 		public Object visit(TimestampAttribute field, Object data) {
900 			return "&nbsp;";
901 		}
902 
903 		public Object visit(SecurityAttribute field, Object data) {
904 			return "&nbsp;";
905 		}
906 
907 		public Object visit(SetAttribute field, Object data) {
908 			// has possibility of changing entity structure
909 			setChangedRowElement(true);
910 
911 			HtmlBuffer buf = new HtmlBuffer();
912 
913 			if (SetAttribute.OPTION_M2M.equals(field.getOption())) {
914 				StringAttribute attr = (StringAttribute) EntityUtils
915 						.getTheOtherAttribute(field);
916 				bindStringRectriction(buf, attr);
917 			} else {
918 				bindRefEntitySelect(buf, field);
919 			}
920 
921 			return buf.toString();
922 		}
923 
924 		public Object visit(FkAttribute field, Object data) {
925 
926 			// has possibility of changing entity structure
927 			setChangedRowElement(true);
928 
929 			HtmlBuffer buf = new HtmlBuffer();
930 
931 			bindEntitySelect(buf, field);
932 
933 			return buf.toString();
934 		}
935 
936 		private void bindStringRectriction(HtmlBuffer buf, StringAttribute attr) {
937 			String[] labelArray = (attr != null) ? attr.getRestrictions()
938 					: null;
939 
940 			int defaultInputSize = 1;
941 			if (attr != null
942 					&& !SetAttribute.OPTION_M2M.equals(attr.getOption())) {
943 				defaultInputSize += 2;
944 				boolean radioSelected = StringAttribute.FORM_RADIO.equals(attr
945 						.getFormType());
946 				Input radio = new Input(Input.RADIO, prefix_ + "formType",
947 						StringAttribute.FORM_COMBOBOX);
948 				radio.setChecked(!radioSelected);
949 				buf.appendBody(radio.toString());
950 				buf.appendBody(getMessage("stringfield.formtype.pulldown"));
951 
952 				buf.appendRadio(prefix_ + "formType",
953 						StringAttribute.FORM_RADIO, radioSelected);
954 				buf.appendBody(getMessage("stringfield.formtype.check"));
955 				buf.appendBr();
956 			}
957 
958 			int columnIndex = FORM_EXTRAFORM;
959 			if (easyMode) {
960 				columnIndex -= 2;
961 			}
962 
963 			String onclick = ValidatorUtils.getAddStringArrayFunction(index_,
964 					columnIndex, defaultInputSize);
965 			Input button = new Input(Input.BUTTON, "",
966 					getMessage("button.listadd"));
967 			button.setOnClick(onclick);
968 			buf.appendBody(button.toString());
969 
970 			onclick = ValidatorUtils.getRemoveStringArrayFunction(index_,
971 					columnIndex);
972 			button = new Input(Input.BUTTON, "",
973 					getMessage("button.listremove"));
974 			button.setOnClick(onclick);
975 			buf.appendBody(button.toString());
976 
977 			buf.setNewline(false);
978 			Div div = new Div();
979 			if (labelArray != null) {
980 				for (int i = 0; i < labelArray.length; i++) {
981 					Span span = new Span().addElement((i + 1) + ".");
982 					Input input = new Input(Input.TEXT, prefix_
983 							+ "restrictions", labelArray[i]);
984 					input.setSize(20);
985 					input.setMaxlength(24);
986 					span.addElement(input).addElement(new BR());
987 					div.addElement(span);
988 				}
989 			} else {
990 				Span span = new Span().addElement("1.");
991 				Input input = new Input(Input.TEXT, prefix_ + "restrictions");
992 				input.setSize(20);
993 				input.setMaxlength(24);
994 				if (errorPosition.contains(index_ + "-" + FORM_EXTRAFORM)) {
995 					input.setClass("errorfield");
996 				}
997 				span.addElement(input).addElement(new BR());
998 				div.addElement(span);
999 			}
1000 			buf.appendBody(div.toString());
1001 			buf.setNewline(true);
1002 		}
1003 
1004 		private void bindSelect(HtmlBuffer buf, String name,
1005 				String[] valueArray, String labelPrefix, String selectedValue) {
1006 			buf.appendStartTag("select");
1007 			buf.appendAttribute("name", name);
1008 			for (int i = 0; i < valueArray.length; i++) {
1009 				String value = valueArray[i];
1010 				String label = getMessage(labelPrefix + value);
1011 				buf.appendOption(label, value, selectedValue);
1012 			}
1013 			buf.endTag();
1014 		}
1015 
1016 		private void bindEntitySelect(HtmlBuffer buf, FkAttribute field) {
1017 			// prepare
1018 			List entityList = entityService_.getNewRefList(entity_);
1019 
1020 			String parentName = prefix_ + "refEntityName";
1021 			String childName = prefix_ + "refEntityFilter";
1022 
1023 			String parent = "document.getElementsByName('" + parentName
1024 					+ "')[0]";
1025 			String child = "document.getElementsByName('" + childName + "')[0]";
1026 			String script = "changeRefFilter(" + parent + "," + child + ");";
1027 
1028 			// start Tag
1029 			buf.appendStartTag(HtmlBuffer.TAG_SLECT);
1030 			buf.appendAttribute("name", parentName);
1031 			buf.appendAttribute("onchange", script);
1032 
1033 			Iterator itr = entityList.iterator();
1034 			while (itr.hasNext()) {
1035 				TgwEntity anEntity = (TgwEntity) itr.next();
1036 				if (anEntity.equals(getEntity())) {
1037 					continue;
1038 				}
1039 				buf.appendOption(anEntity.getDisplayName(), anEntity.getName(),
1040 						field.getRefEntityName());
1041 			}
1042 			buf.endTag();
1043 			buf.appendBr();
1044 
1045 			String refEntityName = field.getRefEntityFilter();
1046 			String refEntityFilter = field.getRefEntityFilter();
1047 
1048 			buf.appendStartTag(HtmlBuffer.TAG_SLECT);
1049 			buf.appendAttribute("name", childName);
1050 			buf.appendOption("-", "");
1051 			if (refEntityName == null || field.getRefEntityFilter() == null) {
1052 				buf.endTag();
1053 				buf.appendStartTag("script");
1054 				buf.appendBody(script);
1055 			} else {
1056 				EntityInfo info = entityService_.createEntityInfo(entity_
1057 						.getDomainName(), field.getRefEntityName());
1058 				for (Iterator fItr = info.getDataFilterList().iterator(); fItr
1059 						.hasNext();) {
1060 					CriteriaExeFunction exe = (CriteriaExeFunction) fItr.next();
1061 					buf.appendOption(exe.getName(), exe.getName(),
1062 							refEntityFilter);
1063 				}
1064 			}
1065 			buf.endTag();
1066 		}
1067 
1068 		private void bindRefEntitySelect(HtmlBuffer buf, SetAttribute field) {
1069 			// start Tag
1070 			buf.appendStartTag(HtmlBuffer.TAG_SLECT);
1071 			buf.appendAttribute("name", prefix_ + "refEntityName");
1072 
1073 			Iterator itr = getEntity().getReferencedFkFieldList().iterator();
1074 			while (itr.hasNext()) {
1075 				FkAttribute fkField = (FkAttribute) itr.next();
1076 				TgwEntity entity = fkField.getEntity();
1077 				if (entity.equals(getEntity())) {
1078 					continue;
1079 				}
1080 				buf.appendOption(entity.getDisplayName(), entity.getName(),
1081 						field.getRefEntityName());
1082 			}
1083 
1084 			if (EntityUtils.hasSelfAttribute(entity_)) {
1085 				buf.appendOption(entity_.getDisplayName(), entity_.getName(),
1086 						field.getRefEntityName());
1087 			}
1088 			// end Tag
1089 			buf.endTag();
1090 		}
1091 	}
1092 
1093 	/***
1094 	 * カラムのフォームの入力値をチェックするVisitor
1095 	 * 
1096 	 * @author hatanaka
1097 	 */
1098 	public class ValidationVisitor implements TgwAttributeVisitor {
1099 		private ActionErrors errors = null;
1100 
1101 		private int index = -1;
1102 
1103 		public ValidationVisitor(ActionErrors errors, int index) {
1104 			this.errors = errors;
1105 			this.index = index;
1106 		}
1107 
1108 		private void commonCheck(TgwAttribute field) {
1109 			if (GenericValidator.isBlankOrNull(field.getDisplayName())) {
1110 				errors.add("column", new ActionMessage("errors.required",
1111 						getMessage("form.entityForm.displayName")));
1112 				errorPosition.add(index + "-" + FORM_DISPLAYNAME);
1113 			} else if (containsOgnlInvalidChar(field.getDisplayName())) {
1114 				errors.add("column", new ActionMessage("errors.invalid",
1115 						getMessage("form.entityForm.displayName")));
1116 				errorPosition.add(index + "-" + FORM_DISPLAYNAME);
1117 			}
1118 
1119 			if (!easyMode) {
1120 				if (GenericValidator.isBlankOrNull(field.getName())) {
1121 					errors.add("column", new ActionMessage("errors.required",
1122 							getMessage("form.entityForm.columnName")));
1123 					errorPosition.add(index + "-" + FORM_COLUMNNAME);
1124 				}
1125 			}
1126 		}
1127 
1128 		private boolean containsOgnlInvalidChar(String str) {
1129 			return StringUtils.contains(str, ">")
1130 					|| StringUtils.contains(str, "<")
1131 					|| StringUtils.contains(str, "&")
1132 					|| StringUtils.contains(str, "//")
1133 					|| StringUtils.contains(str, "\"");
1134 
1135 		}
1136 
1137 		public Object visit(StringAttribute field, Object data) {
1138 			commonCheck(field);
1139 
1140 			if (StringAttribute.OPTION_RESTRICTION.equals(field.getOption())) {
1141 				String[] restrictions = field.getRestrictions();
1142 				if (restrictions == null || restrictions.length == 0) {
1143 					errors.add("column", new ActionMessage(
1144 							"error.message.string?restriction"));
1145 					errorPosition.add(index + "-" + FORM_EXTRAFORM);
1146 				}
1147 			}
1148 			return null;
1149 		}
1150 
1151 		public Object visit(IntegerAttribute field, Object data) {
1152 			commonCheck(field);
1153 			return null;
1154 		}
1155 
1156 		public Object visit(FloatAttribute field, Object data) {
1157 			commonCheck(field);
1158 			return null;
1159 		}
1160 
1161 		public Object visit(BooleanAttribute field, Object data) {
1162 			commonCheck(field);
1163 			return null;
1164 		}
1165 
1166 		public Object visit(DateAttribute field, Object data) {
1167 			commonCheck(field);
1168 			return null;
1169 		}
1170 
1171 		public Object visit(FkAttribute field, Object data) {
1172 			commonCheck(field);
1173 			return null;
1174 		}
1175 
1176 		public Object visit(FileAttribute field, Object data) {
1177 			commonCheck(field);
1178 			return null;
1179 		}
1180 
1181 		public Object visit(SetAttribute field, Object data) {
1182 			commonCheck(field);
1183 			if (EntityUtils.isM2MAttribute(field)) { // m2m の時だけ以下のチェックが必要
1184 				String[] restrictions = field.getRestrictions();
1185 				if (restrictions == null || restrictions.length == 0) {
1186 					errors.add("column", new ActionMessage(
1187 							"error.message.string?restriction"));
1188 					errorPosition.add(index + "-" + FORM_EXTRAFORM);
1189 				}
1190 			}
1191 			return null;
1192 		}
1193 
1194 		public Object visit(SelfAttribute field, Object data) {
1195 			commonCheck(field);
1196 			return null;
1197 		}
1198 
1199 		public Object visit(LongAttribute field, Object data) {
1200 			return null;
1201 		}
1202 
1203 		public Object visit(DoubleAttribute field, Object data) {
1204 			return null;
1205 		}
1206 
1207 		public Object visit(TimestampAttribute field, Object data) {
1208 			return null;
1209 		}
1210 
1211 		public Object visit(SecurityAttribute field, Object data) {
1212 			return null;
1213 		}
1214 	}
1215 }