Package ch.agent.crnickl.impl

Source Code of ch.agent.crnickl.impl.ChronicleImpl$Data

/*
*   Copyright 2012 Hauser Olsson GmbH
*
* Licensed 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: ch.agent.crnickl.impl
* Type: ChronicleImpl
* Version: 1.0.0
*/
package ch.agent.crnickl.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import ch.agent.crnickl.T2DBException;
import ch.agent.crnickl.T2DBMsg;
import ch.agent.crnickl.T2DBMsg.D;
import ch.agent.crnickl.api.Attribute;
import ch.agent.crnickl.api.AttributeDefinition;
import ch.agent.crnickl.api.Chronicle;
import ch.agent.crnickl.api.Schema;
import ch.agent.crnickl.api.Series;
import ch.agent.crnickl.api.SeriesDefinition;
import ch.agent.crnickl.api.Surrogate;
import ch.agent.crnickl.api.UpdatableChronicle;

/**
* Default implementation of {@link Chronicle}.
*
* @author Jean-Paul Vetterli
* @version 1.0.0
*/
public class ChronicleImpl extends DBObjectImpl implements Chronicle {

  /**
   * RawData encapsulates the low level members of a chronicle.
   */
  public static class RawData {
    private Surrogate surrogate;
    private String name;
    private String description;
    private Chronicle collection;
    private Surrogate schema;
   
    /**
     * Construct a RawData object.
     */
    public RawData() {
    }
   
    /**
     * Set the name.
     *
     * @param name a string
     */
    public void setName(String name) {
      this.name = name;
    }
   
    /**
     * Set the description.
     *
     * @param description a string
     */
    public void setDescription(String description) {
      this.description = description;
    }
   
    /**
     * Set the surrogate.
     *
     * @param surrogate a surrogate
     */
    public void setSurrogate(Surrogate surrogate) {
      this.surrogate = surrogate;
    }
   
    /**
     * Set the parent chronicle.
     *
     * @param collection a chronicle
     */
    public void setCollection(Chronicle collection) {
      this.collection = collection;
    }
   
    /**
     * Set the schema.
     *
     * @param schema a schema
     */
    public void setSchema(Surrogate schema) {
      this.schema = schema;
    }
   
    /**
     * Return the surrogate.
     *
     * @return a chronicle surrogate
     */
    public Surrogate getSurrogate() {
      return surrogate;
    }
   
    /**
     * Return the parent chronicle.
     *
     * @return the parent chronicle or null
     */
    public Chronicle getCollection() {
      return collection;
    }
   
    /**
     * Return the name.
     *
     * @return the name
     */
    public String getName() {
      return name;
    }
   
    /**
     * Return the description.
     * @return the description
     */
    public String getDescription() {
      return description;
    }
   
    /**
     * Return the schema.
     *
     * @return return a schema surrogate or null
     */
    public Surrogate getSchema() {
      return schema;
    }
  }

  private class Data {
    private String name;
    private String description;
    private Chronicle collection;
    private Schema schema;
  }
 
  private Data data;
 
  /**
   * Construct a {@link Chronicle}.
   *
   * @param surrogate a chronicle surrogate
   */
  public ChronicleImpl(Surrogate surrogate) {
    super(surrogate);
  }
 
  /**
   * Construct a {@link Chronicle}.
   *
   * @param name a string
   * @param description a string
   * @param parent a chronicle or null
   * @param schema a schema or null
   * @param surrogate a surrogate
   */
  protected ChronicleImpl(String name, String description, Chronicle parent, Schema schema, Surrogate surrogate) {
    this(surrogate);
    data = new Data();
    data.name = name;
    data.description = description;
    data.collection = parent;
    data.schema = schema;
  }
 
  /**
   * Construct a {@link Chronicle}.
   *
   * @param rawData a raw data object
   * @throws T2DBException
   */
  public ChronicleImpl(RawData rawData) throws T2DBException {
    super(rawData.getSurrogate());
    Schema schema = null;
    if (rawData.getSchema() != null)
      schema = getDatabase().getSchema(rawData.getSchema());
    data = new Data();
    data.name = rawData.getName();
    data.description = rawData.getDescription();
    data.collection = rawData.getCollection();
    data.schema = schema;
  }

  private void getData() throws T2DBException {
    if (data == null) {
      DatabaseBackend d = getDatabase();
      DatabaseCache c = d.getCache();
      ChronicleImpl e = c == null ? null : c.lookUpChronicle(getSurrogate());
      if (e != null) {
        data = e.data;
//        int log4j; d.getMessageListener().log(Level.INFO, String.format("*** CACHE HIT: %s %d", toString(), c.size()));
      } else {
        Chronicle chronicle = d.getChronicle(this);
        data = ((ChronicleImpl) chronicle).data;
        // cache the "parent"
        if (c != null && data.collection != null)
          c.store((ChronicleImpl) data.collection);
//        int log4j; d.getMessageListener().log(Level.INFO, String.format("*** CACHE MISS: %s %d", toString(),  c.size()));
      }
    }
  }
 
  @Override
  public Chronicle getChronicle(String simpleName, boolean mustExist) throws T2DBException {
    Chronicle chronicle = getDatabase().getChronicleOrNull(this, simpleName);
    if (chronicle == null && mustExist)
      throw T2DBMsg.exception(D.D40102, getName(true), simpleName);
    else
      return chronicle;
  }
 
  @Override
  public Chronicle findChronicle(String fullName, boolean mustExist) throws T2DBException {
    DatabaseCache cache = getDatabase().getCache();
    Chronicle chronicle = cache.lookUpChronicle(fullName);
    if (chronicle == null) {
      String[] parts = getDatabase().getNamingPolicy().split(fullName);
      if (parts[0] == null) {
        chronicle = getDatabase().getTopChronicle();
        boolean isNameSpace = chronicle.getName(true).equals(fullName);
        if (getDatabase().isStrictNameSpaceMode()) {
          // it must be the name space itself
          if (!isNameSpace)
            throw T2DBMsg.exception(D.D40103, chronicle.getName(true), fullName);
        } else {
          // tolerate name space
          if (!isNameSpace) {
            chronicle = chronicle.getChronicle(parts[1], mustExist);
            // cache top level entities
            if (chronicle != null)
              cache.store((ChronicleImpl)chronicle);
          }
        }
      } else {
        chronicle = findChronicle(parts[0], true);
        // cache entities with children
        cache.store((ChronicleImpl)chronicle);
        chronicle = chronicle.getChronicle(parts[1], mustExist);
        // cache the chronicle if it has a schema ?
      }
    }
    return chronicle;
  }

  @Override
  public boolean isTopChronicle() {
    return false;
  }
 
  @Override
  public UpdatableChronicle edit() {
    UpdatableChronicleImpl u = new UpdatableChronicleImpl(getSurrogate());
    if (data != null) {
      ((ChronicleImpl)u).data = data;
      ((ChronicleImpl)u).data.name = data.name;
      ((ChronicleImpl)u).data.description = data.description;
      ((ChronicleImpl)u).data.collection = data.collection;
      ((ChronicleImpl)u).data.schema = data.schema;
    }
    return u;
  }

  /**
   * Force refresh of state on next access.
   */
  protected void update() {
    data = null;
  }

  @Override
  public Chronicle getCollection() throws T2DBException {
    getData();
    return data.collection;
  }

  @Override
  public Collection<Chronicle> getMembers() throws T2DBException {
    return getDatabase().getChroniclesByParent(this);
  }

  @Override
  public Schema getSchema(boolean effective) throws T2DBException {
    getData();
    Schema es = data.schema;
    if (effective && es == null) {
      Chronicle c = getCollection();
      if (c != null)
        es = c.getSchema(effective);
    }
    return es;
  }
 
  @Override
  public String getName(boolean full) throws T2DBException {
    if (full)
      return getDatabase().getNamingPolicy().fullName(getNames());
    else {
      getData();
      return data.name;
    }
  }
 
  @Override
  public List<String> getNames() throws T2DBException {
    List<String> names = null;
    Chronicle collection = getCollection();
    if (collection != null)
      names = collection.getNames();
    else {
      names = new ArrayList<String>();
      names.add(getDatabase().getTopChronicle().getName(false));
    }
    names.add(getName(false));
    return names;
  }

  @Override
  public String getDescription(boolean full) throws T2DBException {
    if (full)
      return getDatabase().getNamingPolicy().fullDescription(getDescriptions());
    else {
      getData();
      return data.description;
    }
  }

  @Override
  public List<String> getDescriptions() throws T2DBException {
    List<String> descriptions = null;
    Chronicle collection = getCollection();
    if (collection != null)
      descriptions = collection.getDescriptions();
    else {
      descriptions = new ArrayList<String>();
      descriptions.add(getDatabase().getTopChronicle().getDescription(false));
    }
    descriptions.add(getDescription(false));
    return descriptions;
  }

  @Override
  public Attribute<?> getAttribute(String attrName, boolean mustExist) throws T2DBException {
    Attribute<?> attribute = null;
    Schema esch = getSchema(true);
    if (esch == null) {
      if (mustExist)
        throw T2DBMsg.exception(D.D40114, getName(true));
    } else {
      AttributeDefinition<?> def = esch.getAttributeDefinition(attrName, mustExist);
      if (def != null) {
        attribute = def.getAttribute();
        List<Chronicle> chronicles = new ArrayList<Chronicle>();
        Chronicle chronicle = this;
        int lastChronicleWithSchema = 0;
        while (chronicle != null && !chronicle.isTopChronicle()) {
          // if chronicle has schema and schema does not have the attribute then break
          Schema sch = chronicle.getSchema(false);
          if (sch != null) {
            if (sch.getAttributeDefinition(def.getNumber(), false) == null)
              break;
            lastChronicleWithSchema = chronicles.size();
          }
          chronicles.add(chronicle);
          chronicle = chronicle.getCollection();
        }
        chronicles = chronicles.subList(0, lastChronicleWithSchema + 1);
        getDatabase().getAttributeValue(chronicles, attribute);
       
      // if not found, the attribute has the default value already set, so do nothing
   
//      // add description from value type list
//      if (attribute.getDescription() == null) {
//        ValueType<?> type = attribute.getProperty().getValueType();
//        if (type.isRestricted()) {
//          String description = type.getValueDescriptions().get(attribute.get());
//          if (description != null) {
//            attribute.setDescription(description);
//          }
//        }
//      }
      }
    }
    return attribute;
  }

  @Override
  public <T> Series<T> getSeries(String name) throws T2DBException {
    Series<T>[] s = getSeries(new String[]{name}, null, true);
    return s[0];
  }
 
  @Override
  public <T> Series<T>[] getSeries(String[] names, Class<T> type, boolean mustBeDefined) throws T2DBException {
    int[] seriesNr = new int[names.length];
    Schema es = getSchema(true);
    if (es == null)
      throw T2DBMsg.exception(D.D40114, getName(true));
    for (int i = 0; i < names.length; i++) {
      SeriesDefinition ss = es.getSeriesDefinition(names[i], mustBeDefined);
      seriesNr[i] = ss == null ? 0 : ss.getNumber();
    }
    Series<T>[] series = getDatabase().getSeries(this, names, seriesNr);
    if (type != null) {
      for (Series<T> s : series) {
        if (s !=null)
          s.typeCheck(type);
      }
    }
    return series;
  }

  @Override
  public Collection<Attribute<?>> getAttributes() throws T2DBException {
    Collection<Attribute<?>> result = new ArrayList<Attribute<?>>();
    Schema schema = getSchema(true);
    if (schema != null) {
      Collection<AttributeDefinition<?>> defs = schema.getAttributeDefinitions();
      for (AttributeDefinition<?> def : defs) {
        if (!def.isComplete())
          throw T2DBMsg.exception(D.D40115, getName(true), def.getNumber());
        result.add(getAttribute(def.getName(), true));
      }
    }
    return result;
  }

  @Override
  public Collection<Series<?>> getSeries() throws T2DBException {
    Collection<Series<?>> result = new ArrayList<Series<?>>();
    Schema schema = getSchema(true);
    if (schema != null) {
      Collection<SeriesDefinition> sss = schema.getSeriesDefinitions();
      String[] names = new String[sss.size()];
      int i = 0;
      for (SeriesDefinition ss : sss) {
        names[i++] = ss.getName();
      }
      Series<?>[] allSeries = getSeries(names, null, true);
      for (Series<?> s : allSeries) {
        if (s != null)
          result.add(s);
      }
    }
    return result;
  }
 
  @Override
  public boolean isMemberOf(Chronicle collection) throws T2DBException {
    if (this.equals(collection))
      return true;
    else {
      if (isTopChronicle())
        return false;
      else
        return ((ChronicleImpl) getCollection()).isMemberOf(collection);
    }
  }

  @Override
  public String toString() {
    try {
      return getName(true);
    } catch (T2DBException e) {
      throw new RuntimeException(e);
    }
  }

}
TOP

Related Classes of ch.agent.crnickl.impl.ChronicleImpl$Data

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.