/* ************************************************************************ # # DivConq # # http://divconq.com/ # # Copyright: # Copyright 2014 eTimeline, LLC. All rights reserved. # # License: # See the license.txt file in the project's top-level directory for details. # # Authors: # * Andy White # ************************************************************************ */ package divconq.schema; import java.util.ArrayList; import java.util.List; import divconq.lang.op.FuncResult; import divconq.lang.op.OperationContext; import divconq.struct.ListStruct; import divconq.struct.RecordStruct; import divconq.struct.Struct; import divconq.util.StringUtil; import divconq.xml.XElement; public class Field { enum ReqTypes { True(1), False(2), IfPresent(3); private int code; private ReqTypes(int c) { code = c; } public int getCode() { return code; } } protected Schema schema = null; protected List<DataType> options = new ArrayList<DataType>(); protected String name = null; protected ReqTypes required = ReqTypes.False; public Field(Schema schema) { this.schema = schema; } public RecordStruct toJsonDef(int lvl) { RecordStruct def = new RecordStruct(); def.setField("Name", this.name); ListStruct rests = new ListStruct(); for (DataType dt : this.options) rests.addItem(dt.toJsonDef(lvl)); def.setField("Options", rests); def.setField("Required", this.required.getCode()); return def; } public void compile(XElement fel) { this.name = fel.getAttribute("Name"); String req = fel.getAttribute("Required"); if ("True".equals(req)) this.required = ReqTypes.True; else if ("IfPresent".equals(req)) this.required = ReqTypes.IfPresent; String t1 = fel.getAttribute("Type"); if (StringUtil.isNotEmpty(t1)) { this.options = this.schema.manager.lookupOptionsType(t1); return; } String f1 = fel.getAttribute("ForeignKey"); if (StringUtil.isNotEmpty(f1)) { this.options = this.schema.manager.lookupOptionsType("Id"); return; } for (XElement dtel : fel.selectAll("*")) { DataType dt = new DataType(this.schema); dt.load(dtel); dt.compile(); this.options.add(dt); } } // don't call this with data == null from a field if field required - required means "not null" so put the error in public void validate(boolean present, Struct data) { if (data == null) { this.valueUnresolved(present, data); return; } if (this.options.size() == 0) { OperationContext.get().errorTr(423, data); return; } if (this.options.size() == 1) { if (!this.options.get(0).validate(data)) this.valueUnresolved(present, data); return; } for (DataType dt : this.options) { if (dt.match(data)) { if (!dt.validate(data)) this.valueUnresolved(present, data); return; } } OperationContext.get().errorTr(440, data); return; } // don't call this with data == null from a field if field required - required means "not null" so put the error in public Struct normalizeValidate(boolean present, Struct data) { if (data == null) { this.valueUnresolved(present, data); return null; } if (this.options.size() == 0) { OperationContext.get().errorTr(423, data); return null; } if (this.options.size() == 1) { Struct nv = this.options.get(0).normalizeValidate(data); if (nv == null) { this.valueUnresolved(present, data); return null; } return nv; } for (DataType dt : this.options) { if (dt.match(data)) { Struct nv = dt.normalizeValidate(data); if (nv == null) { this.valueUnresolved(present, data); return null; } return nv; } } OperationContext.get().errorTr(440, data); return null; } protected void valueUnresolved(boolean present, Object data) { if (data != null) { OperationContext.get().errorTr(440, data); return; } if (this.required == ReqTypes.False) return; if (this.required == ReqTypes.IfPresent && !present) return; OperationContext.get().errorTr(424, data, this.name); } public Struct wrap(Object data) { if (data == null) return null; if (this.options.size() == 0) return null; if (this.options.size() == 1) return this.options.get(0).wrap(data); for (DataType dt : this.options) { if (dt.match(data)) return dt.wrap(data); } return null; } public FuncResult<Struct> create() { if (this.options.size() == 0) return null; return this.options.get(0).create(); } public DataType getPrimaryType() { if (this.options.size() == 0) return null; return this.options.get(0); } }