You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by li...@apache.org on 2015/07/22 06:13:09 UTC
[19/47] incubator-kylin git commit: KYLIN-875 rename modules:
core-common, core-cube, core-dictionary, core-cube
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
new file mode 100644
index 0000000..c3c9352
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataModelDesc.java
@@ -0,0 +1,310 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.metadata.model;
+
+import java.util.*;
+
+import org.apache.commons.lang.ArrayUtils;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.collect.Sets;
+import org.apache.kylin.common.persistence.ResourceStore;
+import org.apache.kylin.common.persistence.RootPersistentEntity;
+import org.apache.kylin.common.util.StringUtil;
+import org.apache.kylin.metadata.MetadataConstants;
+
+@JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
+public class DataModelDesc extends RootPersistentEntity {
+
+ public static enum RealizationCapacity {
+ SMALL, MEDIUM, LARGE
+ }
+
+ @JsonProperty("name")
+ private String name;
+
+ @JsonProperty("description")
+ private String description;
+
+ @JsonProperty("fact_table")
+ private String factTable;
+
+ @JsonProperty("lookups")
+ private LookupDesc[] lookups;
+
+ @JsonProperty("dimensions")
+ private List<DimensionDesc> dimensions;
+
+ @JsonProperty("metrics")
+ private String[] metrics;
+
+ @JsonProperty("filter_condition")
+ private String filterCondition;
+ @JsonProperty("partition_desc")
+ PartitionDesc partitionDesc;
+
+ @JsonProperty("capacity")
+ private RealizationCapacity capacity = RealizationCapacity.MEDIUM;
+
+
+ /**
+ * Error messages during resolving json metadata
+ */
+ private List<String> errors = new ArrayList<String>();
+
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public Collection<String> getAllTables() {
+ HashSet<String> ret = Sets.newHashSet();
+ ret.add(factTable);
+ for (LookupDesc lookupDesc : lookups)
+ ret.add(lookupDesc.getTable());
+ return ret;
+ }
+
+ public String getFactTable() {
+ return factTable;
+ }
+
+ public void setFactTable(String factTable) {
+ this.factTable = factTable.toUpperCase();
+ }
+
+ public LookupDesc[] getLookups() {
+ return lookups;
+ }
+
+ public void setLookups(LookupDesc[] lookups) {
+ this.lookups = lookups;
+ }
+
+ public boolean isFactTable(String factTable) {
+ return this.factTable.equalsIgnoreCase(factTable);
+ }
+
+ public String getFilterCondition() {
+ return filterCondition;
+ }
+
+ public void setFilterCondition(String filterCondition) {
+ this.filterCondition = filterCondition;
+ }
+
+ public PartitionDesc getPartitionDesc() {
+ return partitionDesc;
+ }
+
+ public void setPartitionDesc(PartitionDesc partitionDesc) {
+ this.partitionDesc = partitionDesc;
+ }
+
+ public RealizationCapacity getCapacity() {
+ return capacity;
+ }
+
+ public void setCapacity(RealizationCapacity capacity) {
+ this.capacity = capacity;
+ }
+
+ public TblColRef findPKByFK(TblColRef fk, String joinType) {
+ assert isFactTable(fk.getTable());
+
+ TblColRef candidate = null;
+
+ for (LookupDesc dim : lookups) {
+ JoinDesc join = dim.getJoin();
+ if (join == null)
+ continue;
+
+ if(joinType != null && !joinType.equals(join.getType()))
+ continue;
+
+ int find = ArrayUtils.indexOf(join.getForeignKeyColumns(), fk);
+ if (find >= 0) {
+ candidate = join.getPrimaryKeyColumns()[find];
+ if (join.getForeignKeyColumns().length == 1) { // is single
+ // column join?
+ break;
+ }
+ }
+ }
+ return candidate;
+ }
+
+ public void init(Map<String, TableDesc> tables) {
+ initJoinColumns(tables);
+ DimensionDesc.capicalizeStrings(dimensions);
+ initPartitionDesc(tables);
+ }
+
+ private void initPartitionDesc(Map<String, TableDesc> tables) {
+ if (this.partitionDesc != null)
+ this.partitionDesc.init(tables);
+ }
+
+ private void initJoinColumns(Map<String, TableDesc> tables) {
+ // join columns may or may not present in cube;
+ // here we don't modify 'allColumns' and 'dimensionColumns';
+ // initDimensionColumns() will do the update
+ for (LookupDesc lookup : this.lookups) {
+ lookup.setTable(lookup.getTable().toUpperCase());
+ TableDesc dimTable = tables.get(lookup.getTable());
+ if (dimTable == null) {
+ throw new IllegalStateException("Table " + lookup.getTable() + " does not exist for " + this);
+ }
+
+ JoinDesc join = lookup.getJoin();
+ if (join == null)
+ continue;
+
+ StringUtil.toUpperCaseArray(join.getForeignKey(), join.getForeignKey());
+ StringUtil.toUpperCaseArray(join.getPrimaryKey(), join.getPrimaryKey());
+ // primary key
+ String[] pks = join.getPrimaryKey();
+ TblColRef[] pkCols = new TblColRef[pks.length];
+ for (int i = 0; i < pks.length; i++) {
+ ColumnDesc col = dimTable.findColumnByName(pks[i]);
+ if (col == null) {
+ throw new IllegalStateException("Can't find column " + pks[i] + " in table " + dimTable.getIdentity());
+ }
+ TblColRef colRef = new TblColRef(col);
+ pks[i] = colRef.getName();
+ pkCols[i] = colRef;
+ }
+ join.setPrimaryKeyColumns(pkCols);
+ // foreign key
+ TableDesc factTable = tables.get(this.factTable.toUpperCase());
+ if (factTable == null) {
+ throw new IllegalStateException("Fact table does not exist:" + this.getFactTable());
+ }
+ String[] fks = join.getForeignKey();
+ TblColRef[] fkCols = new TblColRef[fks.length];
+ for (int i = 0; i < fks.length; i++) {
+ ColumnDesc col = factTable.findColumnByName(fks[i]);
+ if (col == null) {
+ throw new IllegalStateException("Can't find column " + fks[i] + " in table " + this.getFactTable());
+ }
+ TblColRef colRef = new TblColRef(col);
+ fks[i] = colRef.getName();
+ fkCols[i] = colRef;
+ }
+ join.setForeignKeyColumns(fkCols);
+ // Validate join in dimension
+ if (pkCols.length != fkCols.length) {
+ throw new IllegalStateException("Primary keys(" + lookup.getTable() + ")" + Arrays.toString(pks) + " are not consistent with Foreign keys(" + this.getFactTable() + ") " + Arrays.toString(fks));
+ }
+ for (int i = 0; i < fkCols.length; i++) {
+ if (!fkCols[i].getDatatype().equals(pkCols[i].getDatatype())) {
+ throw new IllegalStateException("Primary key " + lookup.getTable() + "." + pkCols[i].getName() + "." + pkCols[i].getDatatype() + " are not consistent with Foreign key " + this.getFactTable() + "." + fkCols[i].getName() + "." + fkCols[i].getDatatype());
+ }
+ }
+
+ }
+ }
+
+ /**
+ * Add error info and thrown exception out
+ *
+ * @param message
+ */
+ public void addError(String message) {
+ addError(message, false);
+ }
+
+ /**
+ * @param message
+ * error message
+ * @param silent
+ * if throw exception
+ */
+ public void addError(String message, boolean silent) {
+ if (!silent) {
+ throw new IllegalStateException(message);
+ } else {
+ this.errors.add(message);
+ }
+ }
+
+ public List<String> getError() {
+ return this.errors;
+ }
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ DataModelDesc modelDesc = (DataModelDesc) o;
+
+ if (!name.equals(modelDesc.name))
+ return false;
+ if (!getFactTable().equals(modelDesc.getFactTable()))
+ return false;
+
+ return true;
+ }
+
+
+ @Override
+ public int hashCode() {
+ int result = 0;
+ result = 31 * result + name.hashCode();
+ result = 31 * result + getFactTable().hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "DataModelDesc [name=" + name + "]";
+ }
+
+ public String getResourcePath() {
+ return concatResourcePath(name);
+ }
+
+ public static String concatResourcePath(String descName) {
+ return ResourceStore.DATA_MODEL_DESC_RESOURCE_ROOT + "/" + descName + MetadataConstants.FILE_SURFIX;
+ }
+
+ public List<DimensionDesc> getDimensions() {
+ return dimensions;
+ }
+
+ public String[] getMetrics() {
+ return metrics;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataType.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataType.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataType.java
new file mode 100644
index 0000000..c1b1d23
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/DataType.java
@@ -0,0 +1,306 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.metadata.model;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author yangli9
+ *
+ */
+public class DataType {
+
+ public static final String VALID_TYPES_STRING = "any|char|varchar|boolean|binary" //
+ + "|integer|tinyint|smallint|bigint|decimal|numeric|float|real|double" //
+ + "|date|time|datetime|timestamp|byte|int|short|long|string|hllc" //
+ + "|" + TblColRef.InnerDataTypeEnum.LITERAL.getDataType() //
+ + "|" + TblColRef.InnerDataTypeEnum.DERIVED.getDataType();
+
+ private static final Pattern TYPE_PATTERN = Pattern.compile(
+ // standard sql types, ref:
+ // http://www.w3schools.com/sql/sql_datatypes_general.asp
+ "(" + VALID_TYPES_STRING + ")" + "\\s*" //
+ + "(?:" + "[(]" + "([\\d\\s,]+)" + "[)]" + ")?", Pattern.CASE_INSENSITIVE);
+
+ public static final Set<String> INTEGER_FAMILY = new HashSet<String>();
+ public static final Set<String> NUMBER_FAMILY = new HashSet<String>();
+ public static final Set<String> DATETIME_FAMILY = new HashSet<String>();
+ public static final Set<String> STRING_FAMILY = new HashSet<String>();
+ private static final Set<Integer> HLLC_PRECISIONS = new HashSet<Integer>();
+ private static final Map<String, String> LEGACY_TYPE_MAP = new HashMap<String, String>();
+ static {
+ INTEGER_FAMILY.add("tinyint");
+ INTEGER_FAMILY.add("smallint");
+ INTEGER_FAMILY.add("integer");
+ INTEGER_FAMILY.add("bigint");
+
+ NUMBER_FAMILY.addAll(INTEGER_FAMILY);
+ NUMBER_FAMILY.add("float");
+ NUMBER_FAMILY.add("double");
+ NUMBER_FAMILY.add("decimal");
+ NUMBER_FAMILY.add("real");
+ NUMBER_FAMILY.add("numeric");
+
+ DATETIME_FAMILY.add("date");
+ DATETIME_FAMILY.add("time");
+ DATETIME_FAMILY.add("datetime");
+ DATETIME_FAMILY.add("timestamp");
+
+ STRING_FAMILY.add("varchar");
+ STRING_FAMILY.add("char");
+
+ LEGACY_TYPE_MAP.put("byte", "tinyint");
+ LEGACY_TYPE_MAP.put("int", "integer");
+ LEGACY_TYPE_MAP.put("short", "smallint");
+ LEGACY_TYPE_MAP.put("long", "bigint");
+ LEGACY_TYPE_MAP.put("string", "varchar");
+ LEGACY_TYPE_MAP.put("hllc10", "hllc(10)");
+ LEGACY_TYPE_MAP.put("hllc12", "hllc(12)");
+ LEGACY_TYPE_MAP.put("hllc14", "hllc(14)");
+ LEGACY_TYPE_MAP.put("hllc15", "hllc(15)");
+ LEGACY_TYPE_MAP.put("hllc16", "hllc(16)");
+
+ for (int i = 10; i <= 16; i++)
+ HLLC_PRECISIONS.add(i);
+ }
+
+ private static final ConcurrentMap<DataType, DataType> CACHE = new ConcurrentHashMap<DataType, DataType>();
+
+ public static final DataType ANY = DataType.getInstance("any");
+
+ public static DataType getInstance(String type) {
+ if (type == null)
+ return null;
+
+ DataType dataType = new DataType(type);
+ DataType cached = CACHE.get(dataType);
+ if (cached == null) {
+ CACHE.put(dataType, dataType);
+ cached = dataType;
+ }
+ return cached;
+ }
+
+ // ============================================================================
+
+ private String name;
+ private int precision;
+ private int scale;
+
+ DataType(String datatype) {
+ parseDataType(datatype);
+ }
+
+ private void parseDataType(String datatype) {
+ datatype = datatype.trim().toLowerCase();
+ datatype = replaceLegacy(datatype);
+
+ Matcher m = TYPE_PATTERN.matcher(datatype);
+ if (m.matches() == false)
+ throw new IllegalArgumentException("bad data type -- " + datatype + ", does not match " + TYPE_PATTERN);
+
+ name = replaceLegacy(m.group(1));
+ precision = -1;
+ scale = -1;
+
+ String leftover = m.group(2);
+ if (leftover != null) {
+ String[] parts = leftover.split("\\s*,\\s*");
+ for (int i = 0; i < parts.length; i++) {
+ int n;
+ try {
+ n = Integer.parseInt(parts[i]);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("bad data type -- " + datatype + ", precision/scale not numeric");
+ }
+ if (i == 0)
+ precision = n;
+ else if (i == 1)
+ scale = n;
+ else
+ throw new IllegalArgumentException("bad data type -- " + datatype + ", too many precision/scale parts");
+ }
+ }
+
+ // FIXME 256 for unknown string precision
+ if ((name.equals("char") || name.equals("varchar")) && precision == -1) {
+ precision = 256; // to save memory at frontend, e.g. tableau will
+ // allocate memory according to this
+ }
+
+ // FIXME (19,4) for unknown decimal precision
+ if ((name.equals("decimal") || name.equals("numeric")) && precision == -1) {
+ precision = 19;
+ scale = 4;
+ }
+
+ if (isHLLC() && HLLC_PRECISIONS.contains(precision) == false)
+ throw new IllegalArgumentException("HLLC precision must be one of " + HLLC_PRECISIONS);
+ }
+
+ private String replaceLegacy(String str) {
+ String replace = LEGACY_TYPE_MAP.get(str);
+ return replace == null ? str : replace;
+ }
+
+ public int getSpaceEstimate() {
+ if (isTinyInt()) {
+ return 1;
+ } else if (isSmallInt()) {
+ return 2;
+ } else if (isInt()) {
+ return 4;
+ } else if (isBigInt()) {
+ return 8;
+ } else if (isFloat()) {
+ return 4;
+ } else if (isDouble()) {
+ return 8;
+ } else if (isDecimal()) {
+ return 8;
+ } else if (isHLLC()) {
+ return 1 << precision;
+ }
+ throw new IllegalStateException("The return type : " + name + " is not recognized;");
+ }
+
+ public boolean isStringFamily() {
+ return STRING_FAMILY.contains(name);
+ }
+
+ public boolean isIntegerFamily() {
+ return INTEGER_FAMILY.contains(name);
+ }
+
+ public boolean isNumberFamily() {
+ return NUMBER_FAMILY.contains(name);
+ }
+
+ public boolean isDateTimeFamily() {
+ return DATETIME_FAMILY.contains(name);
+ }
+
+ public boolean isDate() {
+ return name.equals("date");
+ }
+
+ public boolean isTime() {
+ return name.equals("time");
+ }
+
+ public boolean isTimestamp() {
+ return name.equals("timestamp");
+ }
+
+ public boolean isDatetime() {
+ return name.equals("datetime");
+ }
+
+ public boolean isTinyInt() {
+ return name.equals("tinyint");
+ }
+
+ public boolean isSmallInt() {
+ return name.equals("smallint");
+ }
+
+ public boolean isInt() {
+ return name.equals("integer");
+ }
+
+ public boolean isBigInt() {
+ return name.equals("bigint");
+ }
+
+ public boolean isFloat() {
+ return name.equals("float");
+ }
+
+ public boolean isDouble() {
+ return name.equals("double");
+ }
+
+ public boolean isDecimal() {
+ return name.equals("decimal");
+ }
+
+ public boolean isHLLC() {
+ return name.equals("hllc");
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public int getPrecision() {
+ return precision;
+ }
+
+ public int getScale() {
+ return scale;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + precision;
+ result = prime * result + scale;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ DataType other = (DataType) obj;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ if (precision != other.precision)
+ return false;
+ if (scale != other.scale)
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ if (precision < 0 && scale < 0)
+ return name;
+ else if (scale < 0)
+ return name + "(" + precision + ")";
+ else
+ return name + "(" + precision + "," + scale + ")";
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-metadata/src/main/java/org/apache/kylin/metadata/model/DatabaseDesc.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/DatabaseDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/DatabaseDesc.java
new file mode 100644
index 0000000..3269e43
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/DatabaseDesc.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.metadata.model;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author xjiang
+ */
+public class DatabaseDesc {
+ private String name;
+
+ /**
+ * @return the name
+ */
+ public String getName() {
+ return name == null ? "null" : name.toUpperCase();
+ }
+
+ /**
+ * @param name
+ * the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+
+ return "DatabaseDesc [name=" + name + "]";
+ }
+
+ public static HashMap<String, Integer> extractDatabaseOccurenceCounts(Set<TableDesc> tables) {
+ HashMap<String, Integer> databaseCounts = new HashMap<String, Integer>();
+ for (TableDesc tableDesc : tables) {
+ String databaseName = tableDesc.getDatabase();
+ Integer counter = databaseCounts.get(databaseName);
+ if (counter != null)
+ databaseCounts.put(databaseName, counter + 1);
+ else
+ databaseCounts.put(databaseName, 1);
+ }
+ return databaseCounts;
+ }
+
+ public static HashSet<String> extractDatabaseNames(List<TableDesc> tables) {
+ HashSet<String> databaseNames = new HashSet<String>();
+ for (TableDesc tableDesc : tables) {
+ databaseNames.add(tableDesc.getDatabase());
+ }
+ return databaseNames;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-metadata/src/main/java/org/apache/kylin/metadata/model/DimensionDesc.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/DimensionDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/DimensionDesc.java
new file mode 100644
index 0000000..73e71b6
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/DimensionDesc.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.metadata.model;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.kylin.common.util.StringUtil;
+
+import java.util.List;
+
+/**
+ */
+@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE)
+public class DimensionDesc {
+ @JsonProperty("table")
+ private String table;
+ @JsonProperty("columns")
+ private String[] columns;
+
+ public String getTable() {
+ return table;
+ }
+
+ public void setTable(String table) {
+ this.table = table;
+ }
+
+ public String[] getColumns() {
+ return columns;
+ }
+
+ public void setColumns(String[] columns) {
+ this.columns = columns;
+ }
+
+ public static void capicalizeStrings(List<DimensionDesc> dimensions) {
+ if (dimensions != null) {
+ for (DimensionDesc dimensionDesc : dimensions) {
+ dimensionDesc.setTable(dimensionDesc.getTable().toUpperCase());
+ if (dimensionDesc.getColumns() != null) {
+ StringUtil.toUpperCaseArray(dimensionDesc.getColumns(), dimensionDesc.getColumns());
+ }
+ }
+ }
+ }
+
+ public static int getColumnCount(List<DimensionDesc> dimensionDescs) {
+ int count = 0;
+ for (DimensionDesc dimensionDesc : dimensionDescs) {
+ if (dimensionDesc.getColumns() != null) {
+ count += dimensionDesc.getColumns().length;
+ }
+ }
+ return count;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-metadata/src/main/java/org/apache/kylin/metadata/model/FunctionDesc.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/FunctionDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/FunctionDesc.java
new file mode 100644
index 0000000..af125e2
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/FunctionDesc.java
@@ -0,0 +1,223 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.metadata.model;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.Collection;
+
+/**
+ */
+@JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
+public class FunctionDesc {
+
+ public static final String FUNC_SUM = "SUM";
+ public static final String FUNC_MIN = "MIN";
+ public static final String FUNC_MAX = "MAX";
+ public static final String FUNC_COUNT = "COUNT";
+ public static final String FUNC_COUNT_DISTINCT = "COUNT_DISTINCT";
+
+ public static final String PARAMTER_TYPE_CONSTANT = "constant";
+ public static final String PARAMETER_TYPE_COLUMN = "column";
+
+ @JsonProperty("expression")
+ private String expression;
+ @JsonProperty("parameter")
+ private ParameterDesc parameter;
+ @JsonProperty("returntype")
+ private String returnType;
+
+ private DataType returnDataType;
+ private boolean isDimensionAsMetric = false;
+
+ public String getRewriteFieldName() {
+ if (isSum()) {
+ return getParameter().getValue();
+ } else if (isCount()) {
+ return "COUNT__"; // ignores parameter, count(*), count(1), count(col) are all the same
+ } else {
+ return getFullExpression().replaceAll("[(), ]", "_");
+ }
+ }
+
+ public boolean needRewrite() {
+ return !isSum() && !isDimensionAsMetric();
+ }
+
+ public ColumnDesc newFakeRewriteColumn(TableDesc sourceTable) {
+ ColumnDesc fakeCol = new ColumnDesc();
+ fakeCol.setName(getRewriteFieldName());
+ fakeCol.setDatatype(getSQLType().toString());
+ if (isCount())
+ fakeCol.setNullable(false);
+ fakeCol.init(sourceTable);
+ return fakeCol;
+ }
+
+ public boolean isMin() {
+ return FUNC_MIN.equalsIgnoreCase(expression);
+ }
+
+ public boolean isMax() {
+ return FUNC_MAX.equalsIgnoreCase(expression);
+ }
+
+ public boolean isSum() {
+ return FUNC_SUM.equalsIgnoreCase(expression);
+ }
+
+ public boolean isCount() {
+ return FUNC_COUNT.equalsIgnoreCase(expression);
+ }
+
+ public boolean isCountDistinct() {
+ return FUNC_COUNT_DISTINCT.equalsIgnoreCase(expression);
+ }
+
+ public boolean isHolisticCountDistinct() {
+ if (isCountDistinct() && returnDataType != null && returnDataType.isBigInt()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Get Full Expression such as sum(amount), count(1), count(*)...
+ */
+ public String getFullExpression() {
+ StringBuilder sb = new StringBuilder(expression);
+ sb.append("(");
+ if (parameter != null) {
+ sb.append(parameter.getValue());
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public boolean isDimensionAsMetric() {
+ return isDimensionAsMetric;
+ }
+
+ public void setDimensionAsMetric(boolean isDimensionAsMetric) {
+ this.isDimensionAsMetric = isDimensionAsMetric;
+ }
+
+ public String getExpression() {
+ return expression;
+ }
+
+ public void setExpression(String expression) {
+ this.expression = expression;
+ }
+
+ public ParameterDesc getParameter() {
+ return parameter;
+ }
+
+ public void setParameter(ParameterDesc parameter) {
+ this.parameter = parameter;
+ }
+
+ public DataType getSQLType() {
+ if (isCountDistinct())
+ return DataType.ANY;
+ else if (isSum() || isMax() || isMin())
+ return parameter.getColRefs().get(0).getType();
+ else
+ return returnDataType;
+ }
+
+ public String getReturnType() {
+ return returnType;
+ }
+
+ public DataType getReturnDataType() {
+ return returnDataType;
+ }
+
+ public void setReturnType(String returnType) {
+ this.returnType = returnType;
+ this.initReturnDataType();
+ }
+
+ // Jackson does not provide object post-processing currently
+ public void initReturnDataType() {
+ this.returnDataType = DataType.getInstance(returnType);
+ }
+
+ public TblColRef selectTblColRef(Collection<TblColRef> metricColumns, String factTableName) {
+ if (this.isCount())
+ return null; // count is not about any column but the whole row
+
+ ParameterDesc parameter = this.getParameter();
+ if (parameter == null)
+ return null;
+
+ String columnName = parameter.getValue();
+ for (TblColRef col : metricColumns) {
+ if (col.isSameAs(factTableName, columnName)) {
+ return col;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((expression == null) ? 0 : expression.hashCode());
+ result = prime * result + ((isCount() || parameter == null) ? 0 : parameter.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ FunctionDesc other = (FunctionDesc) obj;
+ if (expression == null) {
+ if (other.expression != null)
+ return false;
+ } else if (!expression.equals(other.expression))
+ return false;
+ // NOTE: don't check the parameter of count()
+ if (isCount() == false) {
+ if (parameter == null) {
+ if (other.parameter != null)
+ return false;
+ } else if (!parameter.equals(other.parameter))
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "FunctionDesc [expression=" + expression + ", parameter=" + parameter + ", returnType=" + returnType + "]";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-metadata/src/main/java/org/apache/kylin/metadata/model/IBuildable.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/IBuildable.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/IBuildable.java
new file mode 100644
index 0000000..e6175fd
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/IBuildable.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.metadata.model;
+
+public interface IBuildable {
+
+ public int getSourceType();
+
+ public int getEngineType();
+
+ public int getStorageType();
+}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-metadata/src/main/java/org/apache/kylin/metadata/model/IJoinedFlatTableDesc.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/IJoinedFlatTableDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/IJoinedFlatTableDesc.java
new file mode 100644
index 0000000..0124b9b
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/IJoinedFlatTableDesc.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.metadata.model;
+
+import java.util.List;
+
+/**
+ */
+public interface IJoinedFlatTableDesc {
+
+ public String getTableName();
+
+ public List<IntermediateColumnDesc> getColumnList();
+
+ public DataModelDesc getDataModel();
+
+ public DataModelDesc.RealizationCapacity getCapacity();
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-metadata/src/main/java/org/apache/kylin/metadata/model/IntermediateColumnDesc.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/IntermediateColumnDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/IntermediateColumnDesc.java
new file mode 100644
index 0000000..9dbe63e
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/IntermediateColumnDesc.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.metadata.model;
+
+import org.apache.kylin.metadata.model.TblColRef;
+
+/**
+ */
+public class IntermediateColumnDesc {
+ private String id;
+ private TblColRef colRef;
+
+ public IntermediateColumnDesc(String id, TblColRef colRef) {
+ this.id = id;
+ this.colRef = colRef;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public TblColRef getColRef() {
+ return this.colRef;
+ }
+
+ public String getColumnName() {
+ return colRef.getName();
+ }
+
+ public String getDataType() {
+ return colRef.getDatatype();
+ }
+
+ public String getTableName() {
+ return colRef.getTable();
+ }
+
+ public boolean isSameAs(String tableName, String columnName) {
+ return colRef.isSameAs(tableName, columnName);
+ }
+
+ public String getCanonicalName() {
+ return colRef.getCanonicalName();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-metadata/src/main/java/org/apache/kylin/metadata/model/JoinDesc.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/JoinDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/JoinDesc.java
new file mode 100644
index 0000000..da907b9
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/JoinDesc.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.metadata.model;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.Arrays;
+
+/**
+ */
+@JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
+public class JoinDesc {
+
+ // inner, left, right, outer...
+ @JsonProperty("type")
+ private String type;
+ @JsonProperty("primary_key")
+ private String[] primaryKey;
+ @JsonProperty("foreign_key")
+ private String[] foreignKey;
+
+ private TblColRef[] primaryKeyColumns;
+ private TblColRef[] foreignKeyColumns;
+
+ public void swapPKFK() {
+ String[] t = primaryKey;
+ primaryKey = foreignKey;
+ foreignKey = t;
+
+ TblColRef[] tt = primaryKeyColumns;
+ primaryKeyColumns = foreignKeyColumns;
+ foreignKeyColumns = tt;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String[] getPrimaryKey() {
+ return primaryKey;
+ }
+
+ public void setPrimaryKey(String[] primaryKey) {
+ this.primaryKey = primaryKey;
+ }
+
+ public String[] getForeignKey() {
+ return foreignKey;
+ }
+
+ public void setForeignKey(String[] foreignKey) {
+ this.foreignKey = foreignKey;
+ }
+
+ public TblColRef[] getPrimaryKeyColumns() {
+ return primaryKeyColumns;
+ }
+
+ public void setPrimaryKeyColumns(TblColRef[] primaryKeyColumns) {
+ this.primaryKeyColumns = primaryKeyColumns;
+ }
+
+ public TblColRef[] getForeignKeyColumns() {
+ return foreignKeyColumns;
+ }
+
+ public void setForeignKeyColumns(TblColRef[] foreignKeyColumns) {
+ this.foreignKeyColumns = foreignKeyColumns;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode(primaryKeyColumns);
+ result = prime * result + Arrays.hashCode(foreignKeyColumns);
+ result = prime * result + this.type.hashCode();
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ JoinDesc other = (JoinDesc) obj;
+
+ if (!this.columnsEqualIgnoringOrder(foreignKeyColumns, other.foreignKeyColumns))
+ return false;
+ if (!this.columnsEqualIgnoringOrder(primaryKeyColumns, other.primaryKeyColumns))
+ return false;
+
+ if (!this.type.equalsIgnoreCase(other.getType()))
+ return false;
+ return true;
+ }
+
+ private boolean columnsEqualIgnoringOrder(TblColRef[] a, TblColRef[] b) {
+ if (a.length != b.length)
+ return false;
+
+ return Arrays.asList(a).containsAll(Arrays.asList(b));
+ }
+
+ @Override
+ public String toString() {
+ return "JoinDesc [type=" + type + ", primary_key=" + Arrays.toString(primaryKey) + ", foreign_key=" + Arrays.toString(foreignKey) + "]";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-metadata/src/main/java/org/apache/kylin/metadata/model/LookupDesc.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/LookupDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/LookupDesc.java
new file mode 100644
index 0000000..1904c0a
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/LookupDesc.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.metadata.model;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+
+@JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
+public class LookupDesc {
+
+ @JsonProperty("table")
+ private String table;
+
+ @JsonProperty("join")
+ private JoinDesc join;
+
+ public String getTable() {
+ return table;
+ }
+
+ public void setTable(String table) {
+ this.table = table;
+ }
+
+ public JoinDesc getJoin() {
+ return join;
+ }
+
+ public void setJoin(JoinDesc join) {
+ this.join = join;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-metadata/src/main/java/org/apache/kylin/metadata/model/MeasureDesc.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/MeasureDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/MeasureDesc.java
new file mode 100644
index 0000000..7237588
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/MeasureDesc.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.metadata.model;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ */
+
+@JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
+public class MeasureDesc {
+
+ @JsonProperty("id")
+ private int id;
+ @JsonProperty("name")
+ private String name;
+ @JsonProperty("function")
+ private FunctionDesc function;
+ @JsonProperty("dependent_measure_ref")
+ private String dependentMeasureRef;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public FunctionDesc getFunction() {
+ return function;
+ }
+
+ public void setFunction(FunctionDesc function) {
+ this.function = function;
+ }
+
+ public String getDependentMeasureRef() {
+ return dependentMeasureRef;
+ }
+
+ public void setDependentMeasureRef(String dependentMeasureRef) {
+ this.dependentMeasureRef = dependentMeasureRef;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ MeasureDesc that = (MeasureDesc) o;
+
+ if (!function.equals(that.getFunction()))
+ return false;
+
+ if (dependentMeasureRef != null && that.getDependentMeasureRef() == null
+ || dependentMeasureRef == null && that.getDependentMeasureRef() != null)
+ return false;
+
+ if (dependentMeasureRef == null && that.getDependentMeasureRef() == null)
+ return true;
+
+ return dependentMeasureRef.equalsIgnoreCase(that.getDependentMeasureRef());
+ }
+
+ @Override
+ public int hashCode() {
+ return id;
+ }
+
+ @Override
+ public String toString() {
+ return "MeasureDesc [name=" + name + ", function=" + function + "]";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-metadata/src/main/java/org/apache/kylin/metadata/model/ParameterDesc.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/ParameterDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/ParameterDesc.java
new file mode 100644
index 0000000..14a073f
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/ParameterDesc.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.metadata.model;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.hadoop.util.StringUtils;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ */
+@JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
+public class ParameterDesc {
+
+ public static final String COLUMN_TYPE = "column";
+
+ @JsonProperty("type")
+ private String type;
+ @JsonProperty("value")
+ private String value;
+
+ private List<TblColRef> colRefs;
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public byte[] getBytes() throws UnsupportedEncodingException {
+ return value.getBytes("UTF-8");
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public List<TblColRef> getColRefs() {
+ return colRefs;
+ }
+
+ public void setColRefs(List<TblColRef> colRefs) {
+ this.colRefs = colRefs;
+ }
+
+ public boolean isColumnType() {
+ return COLUMN_TYPE.equals(type);
+ }
+
+ public void normalizeColumnValue() {
+ if (isColumnType()) {
+ String values[] = value.split("\\s*,\\s*");
+ for (int i = 0; i < values.length; i++)
+ values[i] = values[i].toUpperCase();
+ Arrays.sort(values);
+ value = StringUtils.join(",", values);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((type == null) ? 0 : type.hashCode());
+ result = prime * result + ((value == null) ? 0 : value.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ParameterDesc other = (ParameterDesc) obj;
+ if (type == null) {
+ if (other.type != null)
+ return false;
+ } else if (!type.equals(other.type))
+ return false;
+ if (value == null) {
+ if (other.value != null)
+ return false;
+ } else if (!value.equals(other.value))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "ParameterDesc [type=" + type + ", value=" + value + "]";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-metadata/src/main/java/org/apache/kylin/metadata/model/PartitionDesc.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/PartitionDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/PartitionDesc.java
new file mode 100644
index 0000000..7ae234c
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/PartitionDesc.java
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.metadata.model;
+
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.kylin.common.util.ClassUtil;
+import org.apache.kylin.common.util.DateFormat;
+import org.apache.kylin.common.util.StringSplitter;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * @author xduo
+ *
+ */
+@JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
+public class PartitionDesc {
+
+ public static enum PartitionType {
+ APPEND, //
+ UPDATE_INSERT // not used since 0.7.1
+ }
+
+ @JsonProperty("partition_date_column")
+ private String partitionDateColumn;
+ @JsonProperty("partition_date_start")
+ private long partitionDateStart = 0L;
+ @JsonProperty("partition_type")
+ private PartitionType partitionType = PartitionType.APPEND;
+ @JsonProperty("partition_condition_builder")
+ private String partitionConditionBuilderClz = DefaultPartitionConditionBuilder.class.getName();
+
+ private TblColRef partitionDateColumnRef;
+ private IPartitionConditionBuilder partitionConditionBuilder;
+
+ public void init(Map<String, TableDesc> tables) {
+ if (StringUtils.isEmpty(partitionDateColumn))
+ return;
+
+ partitionDateColumn = partitionDateColumn.toUpperCase();
+
+ String[] columns = StringSplitter.split(partitionDateColumn, ".");
+
+ if (null != columns && columns.length == 3) {
+ String tableName = columns[0].toUpperCase() + "." + columns[1].toUpperCase();
+
+ TableDesc table = tables.get(tableName);
+ ColumnDesc col = table.findColumnByName(columns[2]);
+ if (col != null) {
+ partitionDateColumnRef = new TblColRef(col);
+ } else {
+ throw new IllegalStateException("The column '" + partitionDateColumn + "' provided in 'partition_date_column' doesn't exist.");
+ }
+ } else {
+ throw new IllegalStateException("The 'partition_date_column' format is invalid: " + partitionDateColumn + ", it should be {db}.{table}.{column}.");
+ }
+
+ partitionConditionBuilder = (IPartitionConditionBuilder) ClassUtil.newInstance(partitionConditionBuilderClz);
+ }
+
+ public boolean isPartitioned() {
+ return partitionDateColumnRef != null;
+ }
+
+ public String getPartitionDateColumn() {
+ return partitionDateColumn;
+ }
+
+ public void setPartitionDateColumn(String partitionDateColumn) {
+ this.partitionDateColumn = partitionDateColumn;
+ }
+
+ public long getPartitionDateStart() {
+ return partitionDateStart;
+ }
+
+ public void setPartitionDateStart(long partitionDateStart) {
+ this.partitionDateStart = partitionDateStart;
+ }
+
+ public PartitionType getCubePartitionType() {
+ return partitionType;
+ }
+
+ public void setCubePartitionType(PartitionType partitionType) {
+ this.partitionType = partitionType;
+ }
+
+ public IPartitionConditionBuilder getPartitionConditionBuilder() {
+ return partitionConditionBuilder;
+ }
+
+ public TblColRef getPartitionDateColumnRef() {
+ return partitionDateColumnRef;
+ }
+
+ // ============================================================================
+
+ public static interface IPartitionConditionBuilder {
+ String buildDateRangeCondition(PartitionDesc partDesc, long startInclusive, long endExclusive, Map<String, String> tableAlias);
+ }
+
+ public static class DefaultPartitionConditionBuilder implements IPartitionConditionBuilder {
+
+ @Override
+ public String buildDateRangeCondition(PartitionDesc partDesc, long startInclusive, long endExclusive, Map<String, String> tableAlias) {
+ String partitionColumnName = partDesc.getPartitionDateColumn();
+
+ // convert to use table alias
+ int indexOfDot = partitionColumnName.lastIndexOf(".");
+ if (indexOfDot > 0) {
+ String partitionTableName = partitionColumnName.substring(0, indexOfDot);
+ if (tableAlias != null && tableAlias.containsKey(partitionTableName))
+ partitionColumnName = tableAlias.get(partitionTableName) + partitionColumnName.substring(indexOfDot);
+ }
+
+ StringBuilder builder = new StringBuilder();
+
+ if (startInclusive > 0) {
+ builder.append(partitionColumnName + " >= '" + DateFormat.formatToDateStr(startInclusive) + "' ");
+ builder.append("AND ");
+ }
+ builder.append(partitionColumnName + " < '" + DateFormat.formatToDateStr(endExclusive) + "'");
+
+ return builder.toString();
+ }
+
+ }
+
+
+ /**
+ * Another implementation of IPartitionConditionBuilder, for the fact tables which have three partition columns "YEAR", "MONTH", and "DAY"; This
+ * class will concat the three columns into yyyy-MM-dd format for query hive;
+ */
+ public static class YearMonthDayPartitionConditionBuilder implements PartitionDesc.IPartitionConditionBuilder {
+
+ @Override
+ public String buildDateRangeCondition(PartitionDesc partDesc, long startInclusive, long endExclusive, Map<String, String> tableAlias) {
+
+ String partitionColumnName = partDesc.getPartitionDateColumn();
+ String partitionTableName;
+
+ // convert to use table alias
+ int indexOfDot = partitionColumnName.lastIndexOf(".");
+ if (indexOfDot > 0) {
+ partitionTableName = partitionColumnName.substring(0, indexOfDot).toUpperCase();
+ } else {
+ throw new IllegalStateException("The partitionColumnName is invalid: " + partitionColumnName);
+ }
+
+ if (tableAlias.containsKey(partitionTableName)) {
+ partitionTableName = tableAlias.get(partitionTableName);
+ }
+
+ String concatField = String.format("CONCAT(%s.YEAR,'-',%s.MONTH,'-',%s.DAY)", partitionTableName, partitionTableName, partitionTableName);
+ StringBuilder builder = new StringBuilder();
+
+ if (startInclusive > 0) {
+ builder.append(concatField + " >= '" + DateFormat.formatToDateStr(startInclusive) + "' ");
+ builder.append("AND ");
+ }
+ builder.append(concatField + " < '" + DateFormat.formatToDateStr(endExclusive) + "'");
+
+
+ return builder.toString();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-metadata/src/main/java/org/apache/kylin/metadata/model/SegmentStatusEnum.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/SegmentStatusEnum.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/SegmentStatusEnum.java
new file mode 100644
index 0000000..65c44df
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/SegmentStatusEnum.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.metadata.model;
+
+/**
+ * @author xduo
+ *
+ */
+public enum SegmentStatusEnum {
+ NEW, READY, READY_PENDING
+}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableDesc.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableDesc.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableDesc.java
new file mode 100644
index 0000000..4bc9df3
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/TableDesc.java
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.metadata.model;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.kylin.common.persistence.ResourceStore;
+import org.apache.kylin.common.persistence.RootPersistentEntity;
+import org.apache.kylin.common.util.StringSplitter;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ * Table Metadata from Source. All name should be uppercase.
+ */
+@JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
+public class TableDesc extends RootPersistentEntity {
+ @JsonProperty("name")
+ private String name;
+ @JsonProperty("columns")
+ private ColumnDesc[] columns;
+
+ private DatabaseDesc database = new DatabaseDesc();
+
+ private String identity = null;
+
+ public ColumnDesc findColumnByName(String name) {
+ //ignore the db name and table name if exists
+ int lastIndexOfDot = name.lastIndexOf(".");
+ if (lastIndexOfDot >= 0) {
+ name = name.substring(lastIndexOfDot + 1);
+ }
+
+ for (ColumnDesc c : columns) {
+ // return first matched column
+ if (name.equalsIgnoreCase(c.getName())) {
+ return c;
+ }
+ }
+ return null;
+ }
+
+ public String getResourcePath() {
+ return concatResourcePath(getIdentity());
+ }
+
+ /**
+ * @deprecated this is for compatible with data model v1;
+ * @return
+ */
+ public String getResourcePathV1() {
+ return concatResourcePath(name);
+ }
+
+ public String getIdentity() {
+ if (identity == null) {
+ identity = String.format("%s.%s", this.getDatabase().toUpperCase(), this.getName()).toUpperCase();
+ }
+ return identity;
+ }
+
+ public static String concatResourcePath(String tableIdentity) {
+ return ResourceStore.TABLE_RESOURCE_ROOT + "/" + tableIdentity + ".json";
+ }
+
+ public static String concatExdResourcePath(String tableIdentity) {
+ return ResourceStore.TABLE_EXD_RESOURCE_ROOT + "/" + tableIdentity + ".json";
+ }
+
+ // ============================================================================
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ if (name != null) {
+ String[] splits = StringSplitter.split(name, ".");
+ if (splits.length == 2) {
+ this.setDatabase(splits[0]);
+ this.name = splits[1];
+ } else if (splits.length == 1) {
+ this.name = splits[0];
+ }
+ } else {
+ this.name = name;
+ }
+ }
+
+ @JsonProperty("database")
+ public String getDatabase() {
+ return database.getName();
+ }
+
+ @JsonProperty("database")
+ public void setDatabase(String database) {
+ this.database.setName(database);
+ }
+
+ public ColumnDesc[] getColumns() {
+ return columns;
+ }
+
+ public void setColumns(ColumnDesc[] columns) {
+ this.columns = columns;
+ }
+
+ public int getMaxColumnIndex() {
+ int max = -1;
+ for (ColumnDesc col : columns) {
+ int idx = col.getZeroBasedIndex();
+ max = Math.max(max, idx);
+ }
+ return max;
+ }
+
+ public int getColumnCount() {
+ return getMaxColumnIndex() + 1;
+ }
+
+ public void init() {
+ if (name != null)
+ name = name.toUpperCase();
+
+ if (getDatabase() != null)
+ setDatabase(getDatabase().toUpperCase());
+
+ if (columns != null) {
+ Arrays.sort(columns, new Comparator<ColumnDesc>() {
+ @Override
+ public int compare(ColumnDesc col1, ColumnDesc col2) {
+ Integer id1 = Integer.parseInt(col1.getId());
+ Integer id2 = Integer.parseInt(col2.getId());
+ return id1.compareTo(id2);
+ }
+ });
+
+ for (ColumnDesc col : columns) {
+ col.init(this);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "TableDesc [database=" + getDatabase() + " name=" + name + "]";
+ }
+
+ /** create a mockup table for unit test */
+ public static TableDesc mockup(String tableName) {
+ TableDesc mockup = new TableDesc();
+ mockup.setName(tableName);
+ return mockup;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-metadata/src/main/java/org/apache/kylin/metadata/model/TblColRef.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/TblColRef.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/TblColRef.java
new file mode 100644
index 0000000..caac52a
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/TblColRef.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.metadata.model;
+
+import org.apache.commons.lang.StringUtils;
+
+/**
+ */
+public class TblColRef {
+
+ private static final String INNER_TABLE_NAME = "_kylin_table";
+
+ // used by projection rewrite, see OLAPProjectRel
+ public enum InnerDataTypeEnum {
+
+ LITERAL("_literal_type"), DERIVED("_derived_type");
+
+ private final String dateType;
+
+ private InnerDataTypeEnum(String name) {
+ this.dateType = name;
+ }
+
+ public String getDataType() {
+ return dateType;
+ }
+
+ public static boolean contains(String name) {
+ return LITERAL.getDataType().equals(name) || DERIVED.getDataType().equals(name);
+ }
+ }
+
+ // used by projection rewrite, see OLAPProjectRel
+ public static TblColRef newInnerColumn(String columnName, InnerDataTypeEnum dataType) {
+ ColumnDesc column = new ColumnDesc();
+ column.setName(columnName);
+ TableDesc table = new TableDesc();
+ column.setTable(table);
+ TblColRef colRef = new TblColRef(column);
+ colRef.markInnerColumn(dataType);
+ return colRef;
+ }
+
+ // ============================================================================
+
+ private ColumnDesc column;
+
+ public TblColRef(ColumnDesc column) {
+ this.column = column;
+ }
+
+ public ColumnDesc getColumnDesc() {
+ return column;
+ }
+
+ public void setColumn(ColumnDesc column) {
+ this.column = column;
+ }
+
+ public String getName() {
+ return column.getName();
+ }
+
+ public String getTable() {
+ if (column.getTable() == null) {
+ return null;
+ }
+ return column.getTable().getIdentity();
+ }
+
+ public String getCanonicalName() {
+ return getTable() + "." + getName();
+ }
+
+ public String getDatatype() {
+ return column.getDatatype();
+ }
+
+ public DataType getType() {
+ return column.getType();
+ }
+
+ public void markInnerColumn(InnerDataTypeEnum dataType) {
+ this.column.setDatatype(dataType.getDataType());
+ this.column.getTable().setName(INNER_TABLE_NAME);
+ this.column.getTable().setDatabase("DEFAULT");
+ }
+
+ public boolean isInnerColumn() {
+ return InnerDataTypeEnum.contains(getDatatype());
+ }
+
+ public boolean isDerivedDataType() {
+ return InnerDataTypeEnum.DERIVED.getDataType().equals(getDatatype());
+ }
+
+ /**
+ *
+ * @param tableName full name : db.table
+ * @param columnName columnname
+ * @return
+ */
+ public boolean isSameAs(String tableName, String columnName) {
+ return column.isSameAs(tableName, columnName);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+
+ result = prime * result + column.getTable().getIdentity().hashCode();
+ result = prime * result + column.getName().hashCode();
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ TblColRef other = (TblColRef) obj;
+ if (!StringUtils.equals(column.getTable().getIdentity(), other.column.getTable().getIdentity()))
+ return false;
+ if (!StringUtils.equals(column.getName(), other.column.getName()))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return (column.getTable() == null ? null : column.getTable().getIdentity()) + "." + column.getName();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/7e8896ac/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
----------------------------------------------------------------------
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java b/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
new file mode 100644
index 0000000..d6cbfcc
--- /dev/null
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
@@ -0,0 +1,284 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+package org.apache.kylin.metadata.project;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.kylin.common.persistence.ResourceStore;
+import org.apache.kylin.common.persistence.RootPersistentEntity;
+import org.apache.kylin.metadata.realization.RealizationType;
+
+import javax.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Project is a concept in Kylin similar to schema in DBMS
+ */
+@JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
+public class ProjectInstance extends RootPersistentEntity {
+
+ public static final String DEFAULT_PROJECT_NAME = "DEFAULT";
+
+ @JsonProperty("name")
+ private String name;
+
+ @JsonProperty("tables")
+ private Set<String> tables = new TreeSet<String>();
+
+ @JsonProperty("owner")
+ private String owner;
+
+ @JsonProperty("status")
+ private ProjectStatusEnum status;
+
+ @JsonProperty("create_time_utc")
+ private long createTimeUTC;
+
+ @JsonProperty("last_update_time")
+ // FIXME why not RootPersistentEntity.lastModified??
+ private String lastUpdateTime;
+
+ @JsonProperty("description")
+ private String description;
+
+ @JsonProperty("realizations")
+ private List<RealizationEntry> realizationEntries;
+
+ @JsonProperty("models")
+ private List<String> models;
+
+ public String getResourcePath() {
+ return concatResourcePath(name);
+ }
+
+ public static String concatResourcePath(String projectName) {
+ return ResourceStore.PROJECT_RESOURCE_ROOT + "/" + projectName + ".json";
+ }
+
+ public static String getNormalizedProjectName(String project) {
+ if (project == null)
+ throw new IllegalStateException("Trying to normalized a project name which is null");
+
+ return project.toUpperCase();
+ }
+
+ public static ProjectInstance create(String name, String owner, String description, List<RealizationEntry> realizationEntries,List<String> models) {
+ ProjectInstance projectInstance = new ProjectInstance();
+
+ projectInstance.updateRandomUuid();
+ projectInstance.setName(name);
+ projectInstance.setOwner(owner);
+ projectInstance.setDescription(description);
+ projectInstance.setStatus(ProjectStatusEnum.ENABLED);
+ projectInstance.setCreateTimeUTC(System.currentTimeMillis());
+ if (realizationEntries != null)
+ projectInstance.setRealizationEntries(realizationEntries);
+ else
+ projectInstance.setRealizationEntries(Lists.<RealizationEntry> newArrayList());
+ if (models != null)
+ projectInstance.setModels(models);
+ else
+ projectInstance.setModels(new ArrayList<String>());
+ return projectInstance;
+ }
+
+ // ============================================================================
+
+ public ProjectInstance() {
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public ProjectStatusEnum getStatus() {
+ return status;
+ }
+
+ public void setStatus(ProjectStatusEnum status) {
+ this.status = status;
+ }
+
+ public long getCreateTimeUTC() {
+ return createTimeUTC;
+ }
+
+ public void setCreateTimeUTC(long createTimeUTC) {
+ this.createTimeUTC = createTimeUTC;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public boolean containsRealization(final RealizationType type, final String realization) {
+ return Iterables.any(this.realizationEntries, new Predicate<RealizationEntry>() {
+ @Override
+ public boolean apply(RealizationEntry input) {
+ return input.getType() == type && input.getRealization().equalsIgnoreCase(realization);
+ }
+ });
+ }
+
+ public void removeRealization(final RealizationType type, final String realization) {
+ Iterables.removeIf(this.realizationEntries, new Predicate<RealizationEntry>() {
+ @Override
+ public boolean apply(RealizationEntry input) {
+ return input.getType() == type && input.getRealization().equalsIgnoreCase(realization);
+ }
+ });
+ }
+
+ public List<RealizationEntry> getRealizationEntries(final RealizationType type) {
+ if (type == null)
+ return getRealizationEntries();
+
+ return ImmutableList.copyOf(Iterables.filter(realizationEntries, new Predicate<RealizationEntry>() {
+ @Override
+ public boolean apply(@Nullable RealizationEntry input) {
+ return input.getType() == type;
+ }
+ }));
+ }
+
+ public int getRealizationCount(final RealizationType type) {
+
+ if (type == null)
+ return this.realizationEntries.size();
+
+ return Iterables.size(Iterables.filter(this.realizationEntries, new Predicate<RealizationEntry>() {
+ @Override
+ public boolean apply(RealizationEntry input) {
+ return input.getType() == type;
+ }
+ }));
+ }
+
+ public void addRealizationEntry(final RealizationType type, final String realizationName) {
+ RealizationEntry pdm = new RealizationEntry();
+ pdm.setType(type);
+ pdm.setRealization(realizationName);
+ this.realizationEntries.add(pdm);
+ }
+
+ public void setTables(Set<String> tables) {
+ this.tables = tables;
+ }
+
+ public boolean containsTable(String tableName) {
+ return tables.contains(tableName.toUpperCase());
+ }
+
+ public void removeTable(String tableName) {
+ tables.remove(tableName.toUpperCase());
+ }
+
+ public int getTablesCount() {
+ return this.getTables().size();
+ }
+
+ public void addTable(String tableName) {
+ this.getTables().add(tableName.toUpperCase());
+ }
+
+ public Set<String> getTables() {
+ return tables;
+ }
+
+ public String getOwner() {
+ return owner;
+ }
+
+ public void setOwner(String owner) {
+ this.owner = owner;
+ }
+
+ public void recordUpdateTime(long timeMillis) {
+ this.lastUpdateTime = formatTime(timeMillis);
+ }
+
+ public List<RealizationEntry> getRealizationEntries() {
+ return realizationEntries;
+ }
+
+ public void setRealizationEntries(List<RealizationEntry> entries) {
+ this.realizationEntries = entries;
+ }
+
+ public List<String> getModels() {
+ return models;
+ }
+
+ public boolean containsModel(String modelName) {
+ return models!=null&&models.contains(modelName);
+ }
+
+ public void setModels(List<String> models) { this.models = models; }
+
+ public void addModel(String modelName) {
+ if(this.getModels()==null){
+ this.setModels(new ArrayList<String>());
+ }
+ this.getModels().add(modelName);
+ }
+
+ public void removeModel(String modelName){
+ if(this.getModels()!=null) {
+ this.getModels().remove(modelName);
+ }
+ }
+
+ public void init() {
+ if (name == null)
+ name = ProjectInstance.DEFAULT_PROJECT_NAME;
+
+ if (realizationEntries == null) {
+ realizationEntries = new ArrayList<RealizationEntry>();
+ }
+
+ if (tables == null)
+ tables = new TreeSet<String>();
+
+ if (StringUtils.isBlank(this.name))
+ throw new IllegalStateException("Project name must not be blank");
+ }
+
+ @Override
+ public String toString() {
+ return "ProjectDesc [name=" + name + "]";
+ }
+
+}