com.fujitsu.dc.core.model.impl.es.CellEsImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.fujitsu.dc.core.model.impl.es.CellEsImpl.java

Source

/**
 * personium.io
 * Copyright 2014 FUJITSU LIMITED
 *
 * 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 com.fujitsu.dc.core.model.impl.es;

import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;

import net.spy.memcached.internal.CheckedOperationTimeoutException;

import org.apache.commons.lang.StringUtils;
import org.odata4j.core.OEntity;
import org.odata4j.core.OEntityKey;
import org.odata4j.expression.BoolCommonExpression;
import org.odata4j.producer.EntitiesResponse;
import org.odata4j.producer.EntityResponse;
import org.odata4j.producer.InlineCount;
import org.odata4j.producer.ODataProducer;
import org.odata4j.producer.QueryInfo;
import org.odata4j.producer.resources.OptionsQueryParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fujitsu.dc.common.auth.token.IExtRoleContainingToken;
import com.fujitsu.dc.common.auth.token.Role;
import com.fujitsu.dc.common.es.response.DcGetResponse;
import com.fujitsu.dc.common.es.response.DcSearchHit;
import com.fujitsu.dc.common.es.response.DcSearchHits;
import com.fujitsu.dc.common.es.response.DcSearchResponse;
import com.fujitsu.dc.common.es.util.IndexNameEncoder;
import com.fujitsu.dc.core.DcCoreConfig;
import com.fujitsu.dc.core.DcCoreException;
import com.fujitsu.dc.core.auth.AccessContext;
import com.fujitsu.dc.core.auth.AuthUtils;
import com.fujitsu.dc.core.event.EventBus;
import com.fujitsu.dc.core.model.Box;
import com.fujitsu.dc.core.model.BoxCmp;
import com.fujitsu.dc.core.model.Cell;
import com.fujitsu.dc.core.model.ModelFactory;
import com.fujitsu.dc.core.model.ctl.Account;
import com.fujitsu.dc.core.model.ctl.Common;
import com.fujitsu.dc.core.model.ctl.ExtCell;
import com.fujitsu.dc.core.model.ctl.ExtRole;
import com.fujitsu.dc.core.model.ctl.ReceivedMessage;
import com.fujitsu.dc.core.model.ctl.Relation;
import com.fujitsu.dc.core.model.ctl.SentMessage;
import com.fujitsu.dc.core.model.impl.es.accessor.EntitySetAccessor;
import com.fujitsu.dc.core.model.impl.es.accessor.ODataLinkAccessor;
import com.fujitsu.dc.core.model.impl.es.cache.BoxCache;
import com.fujitsu.dc.core.model.impl.es.cache.CellCache;
import com.fujitsu.dc.core.model.impl.es.doc.OEntityDocHandler;
import com.fujitsu.dc.core.model.impl.es.odata.CellCtlODataProducer;
import com.fujitsu.dc.core.odata.OEntityWrapper;

/**
 * Cell?Es???.
 */
public final class CellEsImpl implements Cell {
    private String id;
    private String name;
    private String url;
    private String owner;
    private Long published;
    private Map<String, Object> json;

    /**
     * Es???.
     */
    private static final int TOP_NUM = DcCoreConfig.getEsTopNum();

    /**
     * .
     */
    static Logger log = LoggerFactory.getLogger(CellEsImpl.class);

    /**
     * .
     */
    public CellEsImpl() {
    }

    @Override
    public EventBus getEventBus() {
        return new EventBus(this);
    }

    @Override
    public boolean isEmpty() {
        CellCtlODataProducer producer = new CellCtlODataProducer(this);
        // ????.
        QueryInfo queryInfo = new QueryInfo(InlineCount.ALLPAGES, null, null, null, null, null, null, null, null);
        if (producer.getEntitiesCount(Box.EDM_TYPE_NAME, queryInfo).getCount() > 0) {
            return false;
        }

        // ???????
        Box defaultBox = this.getBoxForName(Box.DEFAULT_BOX_NAME);
        BoxCmp defaultBoxCmp = ModelFactory.boxCmp(defaultBox);
        if (!defaultBoxCmp.isEmpty()) {
            return false;
        }

        // ??????????
        // TODO v1.1 ??????Type?c:?uuid?????????
        if (producer.getEntitiesCount(Account.EDM_TYPE_NAME, queryInfo).getCount() > 0
                || producer.getEntitiesCount(Role.EDM_TYPE_NAME, queryInfo).getCount() > 0
                || producer.getEntitiesCount(ExtCell.EDM_TYPE_NAME, queryInfo).getCount() > 0
                || producer.getEntitiesCount(ExtRole.EDM_TYPE_NAME, queryInfo).getCount() > 0
                || producer.getEntitiesCount(Relation.EDM_TYPE_NAME, queryInfo).getCount() > 0
                || producer.getEntitiesCount(SentMessage.EDM_TYPE_NAME, queryInfo).getCount() > 0
                || producer.getEntitiesCount(ReceivedMessage.EDM_TYPE_NAME, queryInfo).getCount() > 0) {
            return false;
        }
        // TODO v1.1 Message?????409
        return true;
    }

    @Override
    public void makeEmpty() {
        // TODO 
    }

    @Override
    public Box getBoxForName(String boxName) {
        if (Box.DEFAULT_BOX_NAME.equals(boxName)) {
            return new Box(this, null);
        }

        // URl???Box????????Box??????null??
        if (!validatePropertyRegEx(boxName, Common.PATTERN_NAME)) {
            return null;
        }
        // ??Box???
        Box cachedBox = BoxCache.get(boxName, this);
        if (cachedBox != null) {
            return cachedBox;
        }

        Box loadedBox = null;
        try {
            ODataProducer op = ModelFactory.ODataCtl.cellCtl(this);
            EntityResponse er = op.getEntity("Box", OEntityKey.create(boxName), null);
            loadedBox = new Box(this, er.getEntity());
            BoxCache.cache(loadedBox);
            return loadedBox;
        } catch (RuntimeException e) {
            if (e.getCause() instanceof CheckedOperationTimeoutException) {
                return loadedBox;
            } else {
                return null;
            }
        }
    }

    @Override
    public Box getBoxForSchema(String boxSchema) {
        ODataProducer op = ModelFactory.ODataCtl.cellCtl(this);
        BoolCommonExpression filter = OptionsQueryParser.parseFilter("Schema eq '" + boxSchema + "'");
        QueryInfo qi = QueryInfo.newBuilder().setFilter(filter).build();
        try {
            EntitiesResponse er = op.getEntities("Box", qi);
            List<OEntity> entList = er.getEntities();
            if (entList.size() != 1) {
                return null;
            }
            return new Box(this, entList.get(0));
        } catch (RuntimeException e) {
            return null;
        }
    }

    /**
     * @param uriInfo UriInfo
     * @return Cell  ?Cell????????null
     */
    public static Cell load(final UriInfo uriInfo) {
        URI reqUri = uriInfo.getRequestUri();
        URI baseUri = uriInfo.getBaseUri();

        String rPath = reqUri.getPath();
        String bPath = baseUri.getPath();
        rPath = rPath.substring(bPath.length());
        String[] paths = StringUtils.split(rPath, "/");

        return findCell("s.Name.untouched", paths[0], uriInfo);
    }

    /**
     * @param id id
     * @param uriInfo UriInfo
     * @return Cell  ?Cell????????null
     */
    public static Cell load(final String id, final UriInfo uriInfo) {
        EntitySetAccessor esCells = EsModel.cell();
        DcGetResponse resp = esCells.get(id);
        if (resp.exists()) {
            CellEsImpl ret = new CellEsImpl();
            ret.setJson(resp.getSource());
            ret.id = resp.getId();
            return ret;
        } else {
            return null;
        }
    }

    /**
     * ID ??Cell??Cell?Cell??.
     * @param queryKey Cell??(Cell??)
     * @param queryValue Cell????
     * @param uriInfo UriInfo
     * @return Cell  ?Cell??????????queryKey?????null
     */
    public static Cell findCell(String queryKey, String queryValue, UriInfo uriInfo) {
        if (!queryKey.equals("_id") && !queryKey.equals("s.Name.untouched")) {
            return null;
        }
        // URl???Cell?????????Cell??????null??
        if (!validatePropertyRegEx(queryValue, Common.PATTERN_NAME)) {
            return null;
        }

        EntitySetAccessor ecCells = EsModel.cell();
        CellEsImpl ret = new CellEsImpl();

        Map<String, Object> cache = CellCache.get(queryValue);
        if (cache == null) {
            Map<String, Object> source = new HashMap<String, Object>();
            Map<String, Object> filter = new HashMap<String, Object>();
            Map<String, Object> term = new HashMap<String, Object>();

            term.put(queryKey, queryValue);
            filter.put("term", term);
            source.put("query", QueryMapFactory.filteredQuery(null, filter));

            DcSearchResponse resp = ecCells.search(source);
            if ((resp == null) || (resp.getHits().getCount() == 0)) {
                return null;
            }
            DcSearchHit hit = resp.getHits().getAt(0);
            ret.setJson(hit.getSource());
            ret.id = hit.getId();

            cache = hit.getSource();
            cache.put("_id", hit.getId());
            try {
                CellCache.cache(queryValue, cache);
            } catch (RuntimeException e) {
                if (e.getCause() instanceof CheckedOperationTimeoutException) {
                    // memcached????????????
                    log.info("Faild to cache Cell info.");
                } else {
                    // ??????????
                    throw DcCoreException.Server.SERVER_CONNECTION_ERROR;
                }
            }
        } else {
            ret.setJson(cache);
            ret.id = (String) cache.get("_id");
        }

        // URL???Set
        StringBuilder urlSb = new StringBuilder();
        UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
        uriBuilder.scheme(DcCoreConfig.getUnitScheme());
        urlSb.append(uriBuilder.build().toASCIIString());
        urlSb.append(ret.getName());
        urlSb.append("/");
        ret.url = urlSb.toString();
        return ret;
    }

    /**
     * Map????.
     * @param json ?Map
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public void setJson(Map json) {
        this.json = json;
        if (this.json == null) {
            return;
        }
        Map<String, String> urlJson = (Map<String, String>) json.get("s");
        Map<String, String> hJson = (Map<String, String>) json.get("h");
        this.published = (Long) json.get("p");
        this.name = urlJson.get("Name");
        this.owner = hJson.get("Owner");

    }

    @Override
    public OEntityWrapper getAccount(final String username) {
        ODataProducer op = ModelFactory.ODataCtl.cellCtl(this);
        OEntityKey key = OEntityKey.create(username);
        OEntityWrapper oew = null;
        try {
            EntityResponse resp = op.getEntity("Account", key, null);
            oew = (OEntityWrapper) resp.getEntity();
        } catch (DcCoreException dce) {
            log.debug(dce.getMessage());
        }
        return oew;
    }

    @Override
    public boolean authenticateAccount(final OEntityWrapper oew, final String password) {
        // TODO ?????? ?????ID?????????????
        String cred = null;
        if (oew != null) {
            cred = (String) oew.get("HashedCredential");
        }
        String hCred = AuthUtils.hashPassword(password);
        if (hCred.equals(cred)) {
            return true;
        }

        return false;
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<Role> getRoleListForAccount(final String username) {
        // Account?
        EntitySetAccessor accountType = EsModel.cellCtl(this, Account.EDM_TYPE_NAME);

        List<Map<String, Object>> filters = new ArrayList<Map<String, Object>>();
        filters.add(QueryMapFactory.termQuery("s.Name.untouched", username));

        List<Map<String, Object>> queries = new ArrayList<Map<String, Object>>();
        queries.add(QueryMapFactory.termQuery("c", this.getId()));

        Map<String, Object> query = QueryMapFactory.filteredQuery(null, QueryMapFactory.mustQuery(queries));

        Map<String, Object> source = new HashMap<String, Object>();
        source.put("filter", QueryMapFactory.andFilter(filters));
        source.put("query", query);

        DcSearchHits hits = accountType.search(source).getHits();

        if (hits.getCount() == 0) {
            return null;
        }

        DcSearchHit hit = hits.getHits()[0];

        List<Role> ret = new ArrayList<Role>();
        ODataLinkAccessor links = EsModel.cellCtlLink(this);

        // ???????
        List<Map<String, Object>> searchRoleQueries = new ArrayList<Map<String, Object>>();
        searchRoleQueries.add(QueryMapFactory.termQuery("t1", "Account"));
        searchRoleQueries.add(QueryMapFactory.termQuery("t2", "Role"));

        List<Map<String, Object>> searchRoleFilters = new ArrayList<Map<String, Object>>();
        searchRoleFilters.add(QueryMapFactory.termQuery("k1", hit.getId()));
        Map<String, Object> and = new HashMap<String, Object>();
        and.put("filters", searchRoleFilters);
        Map<String, Object> searchRoleFilter = new HashMap<String, Object>();
        searchRoleFilter.put("and", and);

        Map<String, Object> searchRoleSource = new HashMap<String, Object>();
        searchRoleSource.put("filter", searchRoleFilter);
        searchRoleSource.put("query",
                QueryMapFactory.filteredQuery(null, QueryMapFactory.mustQuery(searchRoleQueries)));

        // ?
        searchRoleSource.put("size", TOP_NUM);

        DcSearchResponse res = links.search(searchRoleSource);
        if (res == null) {
            return ret;
        }
        DcSearchHit[] hits2 = res.getHits().getHits();
        for (DcSearchHit hit2 : hits2) {
            Map<String, Object> row = hit2.getSource();
            String role = (String) row.get("k2");
            log.debug(this.id);
            EntitySetAccessor roleDao = EsModel.cellCtl(this, Role.EDM_TYPE_NAME);
            DcGetResponse gRes = roleDao.get(role);
            if (gRes == null) {
                continue;
            }
            Map<String, Object> src = gRes.getSource();
            Map<String, Object> s = (Map<String, Object>) src.get("s");
            Map<String, Object> l = (Map<String, Object>) src.get("l");
            String roleName = (String) s.get(KEY_NAME);
            String boxId = (String) l.get("Box");
            String boxName = null;
            String schema = null;
            if (boxId != null) {
                // Box?
                EntitySetAccessor box = EsModel.box(this);
                DcGetResponse getRes = box.get(boxId);
                if (getRes == null || !getRes.isExists()) {
                    continue;
                }
                Map<String, Object> boxsrc = getRes.getSource();
                Map<String, Object> boxs = (Map<String, Object>) boxsrc.get("s");
                boxName = (String) boxs.get(KEY_NAME);
                schema = (String) boxs.get(KEY_SCHEMA);
            }
            Role roleObj = new Role(roleName, boxName, schema);

            ret.add(roleObj);
        }
        return ret;
    }

    @Override
    public List<Role> getRoleListHere(final IExtRoleContainingToken token) {
        List<Role> ret = new ArrayList<Role>();

        // ExtCell?Role????????Role
        this.addRoleListExtCelltoRole(token, ret);

        // ExtCell?Relation?Role????????Role
        // ?
        // ExtCell?Relation?ExtRole?Role????????Role
        this.addRoleListExtCelltoRelationAndExtRole(token, ret);

        return ret;
    }

    /**
     * ExtCell?Role??????????Role?.
     * @param token 
     * @param roles ???????
     */
    private void addRoleListExtCelltoRole(final IExtRoleContainingToken token, List<Role> roles) {
        // ExtCell-Role??????Role??
        String extCell = token.getExtCellUrl();
        String principal = token.getSubject();
        String principalCell;
        if (principal.contains("#")) {
            principalCell = token.getSubject().substring(0, principal.indexOf("#"));
        } else {
            principalCell = token.getSubject();
        }

        // ?ExtCell???2??????
        if (extCell.equals(principalCell)) {
            ODataProducer op = ModelFactory.ODataCtl.cellCtl(this);
            EntitiesResponse response = null;
            // ?
            QueryInfo qi = QueryInfo.newBuilder().setTop(TOP_NUM).setInlineCount(InlineCount.NONE).build();
            try {
                // ExtCell-Role??
                response = (EntitiesResponse) op.getNavProperty(ExtCell.EDM_TYPE_NAME, OEntityKey.create(extCell),
                        "_" + Role.EDM_TYPE_NAME, qi);
            } catch (DcCoreException dce) {
                if (DcCoreException.OData.NO_SUCH_ENTITY != dce) {
                    throw dce;
                }
            }
            if (response == null) {
                return;
            }

            // ExtCell-Role???????????????
            List<OEntity> entList = response.getEntities();
            for (OEntity ent : entList) {
                OEntityWrapper entRole = (OEntityWrapper) ent;
                this.addRole(entRole.getUuid(), roles);
            }
        }
    }

    /**
     * ExtCell?Relation?Role????????Role.
     * ?
     * ExtCell?Relation?ExtRole?Role????????Role.
     * @param token 
     * @param roles ???????
     */
    @SuppressWarnings("unchecked")
    private void addRoleListExtCelltoRelationAndExtRole(final IExtRoleContainingToken token, List<Role> roles) {
        String extCell = token.getExtCellUrl();

        // ExtCell-Role??????Role??
        ODataProducer op = ModelFactory.ODataCtl.cellCtl(this);
        EntitiesResponse response = null;
        try {
            // ?
            QueryInfo qi = QueryInfo.newBuilder().setTop(TOP_NUM).setInlineCount(InlineCount.NONE).build();
            // ExtCell-Relation??
            response = (EntitiesResponse) op.getNavProperty(ExtCell.EDM_TYPE_NAME, OEntityKey.create(extCell),
                    "_" + Relation.EDM_TYPE_NAME, qi);
        } catch (DcCoreException dce) {
            if (DcCoreException.OData.NO_SUCH_ENTITY != dce) {
                throw dce;
            }
        }
        if (response == null) {
            return;
        }

        List<OEntity> entList = response.getEntities();
        for (OEntity ent : entList) {
            OEntityWrapper entRelation = (OEntityWrapper) ent;

            // ExtCell-Relation???????????????
            DcSearchResponse res = serchRoleLinks(Relation.EDM_TYPE_NAME, entRelation.getUuid());
            if (res == null) {
                continue;
            }
            this.addRoles(res.getHits().getHits(), roles);
            //  ?????ExtCell?Relation?Role????????Role.?
            //  ????ExtCell?Relation?ExtRole?Role????????Role??.

            // Relation?ExtRole??
            EntitySetAccessor extRoleType = EsModel.cellCtl(this, ExtRole.EDM_TYPE_NAME);

            // Relation??????ExtRole?
            // ????????
            Map<String, Object> source = new HashMap<String, Object>();

            // ?????????
            List<Map<String, Object>> implicitFilters = QueryMapFactory.getImplicitFilters(this.id, null, null,
                    null, extRoleType.getType());
            String linksKey = OEntityDocHandler.KEY_LINK + "." + Relation.EDM_TYPE_NAME;
            implicitFilters.add(0, QueryMapFactory.termQuery(linksKey, entRelation.getUuid()));
            Map<String, Object> query = QueryMapFactory.mustQuery(implicitFilters);
            Map<String, Object> filteredQuery = QueryMapFactory.filteredQuery(null, query);
            source.put("query", filteredQuery);
            long hitNum = extRoleType.count(source);
            // ExtCell???????????
            if (hitNum == 0) {
                continue;
            }
            source.put("size", hitNum);

            DcSearchHits extRoleHits = extRoleType.search(source).getHits();
            // ExtCell???????????
            // ?????????????????
            if (extRoleHits.getCount() == 0) {
                continue;
            }
            for (DcSearchHit extRoleHit : extRoleHits.getHits()) {
                Map<String, Object> extRoleSource = extRoleHit.getSource();
                Map<String, Object> extRoleS = (Map<String, Object>) extRoleSource.get("s");
                String esExtRole = (String) extRoleS.get(ExtRole.EDM_TYPE_NAME);

                // ??????????
                for (Role tokenRole : token.getRoleList()) {
                    if (!tokenRole.createUrl().equals(esExtRole)) {
                        continue;
                    }
                    // ExtCell-Role???????????????
                    DcSearchResponse resExtRoleToRole = serchRoleLinks(ExtRole.EDM_TYPE_NAME, extRoleHit.getId());
                    if (resExtRoleToRole == null) {
                        continue;
                    }
                    this.addRoles(resExtRoleToRole.getHits().getHits(), roles);
                }
            }
        }
    }

    /**
     * Role???????.
     * @param searchKey ????
     * @param searchValue ?uuid
     * @return ?
     */
    private DcSearchResponse serchRoleLinks(final String searchKey, final String searchValue) {

        ODataLinkAccessor links = EsModel.cellCtlLink(this);
        // Relation???????
        Map<String, Object> source = new HashMap<String, Object>();
        Map<String, Object> filter = new HashMap<String, Object>();
        Map<String, Object> and = new HashMap<String, Object>();
        List<Map<String, Object>> filters = new ArrayList<Map<String, Object>>();

        List<Map<String, Object>> queries = new ArrayList<Map<String, Object>>();
        queries.add(QueryMapFactory.termQuery("t1", searchKey));
        queries.add(QueryMapFactory.termQuery("t2", "Role"));

        Map<String, Object> query = QueryMapFactory.filteredQuery(null, QueryMapFactory.mustQuery(queries));

        filters.add(QueryMapFactory.termQuery("k1", searchValue));
        and.put("filters", filters);
        filter.put("and", and);
        source.put("filter", filter);
        source.put("query", query);
        // ?
        source.put("size", TOP_NUM);

        return links.search(source);
    }

    /**
     * Role????SearchHit??????.
     * @param hits Role??
     * @param roles ???????
     */
    private void addRoles(DcSearchHit[] hits, List<Role> roles) {
        for (DcSearchHit hit : hits) {
            Map<String, Object> src = hit.getSource();
            String roleUuid = (String) src.get("k2");

            // Relation-Role???????????????
            this.addRole(roleUuid, roles);
        }
    }

    /**
     * ???.
     * @param uuid Role?UUID
     * @param roles ???????
     */
    @SuppressWarnings("unchecked")
    private void addRole(String uuid, List<Role> roles) {
        EntitySetAccessor roleDao = EsModel.cellCtl(this, Role.EDM_TYPE_NAME);
        DcGetResponse gRes = roleDao.get(uuid);
        if (gRes == null) {
            return;
        }
        Map<String, Object> src = gRes.getSource();
        Map<String, Object> s = (Map<String, Object>) src.get("s");
        Map<String, Object> l = (Map<String, Object>) src.get("l");
        String roleName = (String) s.get(KEY_NAME);
        String schema = (String) s.get(KEY_SCHEMA);
        String boxId = (String) l.get(Box.EDM_TYPE_NAME);
        String boxName = null;
        if (boxId != null) {
            // Box?
            Map<String, Object> boxsrc = DavCmpEsImpl.searchBox(this, boxId);
            Map<String, Object> boxs = (Map<String, Object>) boxsrc.get("s");
            boxName = (String) boxs.get(KEY_NAME);
        }

        roles.add(new Role(roleName, boxName, schema, this.url));
    }

    @Override
    public String getOwner() {
        return this.owner;
    }

    @Override
    public String getUnitUserNameWithOutPrefix() {
        String unitUserName;
        if (this.owner == null) {
            unitUserName = AccessContext.TYPE_ANONYMOUS;
        } else {
            unitUserName = IndexNameEncoder.encodeEsIndexName(owner);
        }
        return unitUserName;
    }

    @Override
    public String getUnitUserName() {
        String unitUserName = DcCoreConfig.getEsUnitPrefix() + "_" + getUnitUserNameWithOutPrefix();
        return unitUserName;
    }

    /**
     * Cell??????.
     * @return Cell??
     */
    @Override
    public String getName() {
        return name;
    }

    /**
     * ??Cell?ID???.
     * @return ID
     */
    @Override
    public String getId() {
        return this.id;
    }

    /**
     * ??Cell?ID???.
     * @param id ID
     */
    public void setId(String id) {
        this.id = id;
    }

    /**
     * ??Cell?URL???.
     * @return URL
     */
    @Override
    public String getUrl() {
        return this.url;
    }

    /**
     * ??Cell?URL???.
     * @param url URL
     */
    public void setUrl(String url) {
        this.url = url;
    }

    static final String KEY_NAME = "Name";
    static final String KEY_SCHEMA = "Schema";

    /**
     * ??????.
     * @param propValue 
     * @param dcFormat dcFormat?
     * @return ???false?
     */
    private static boolean validatePropertyRegEx(String propValue, String dcFormat) {
        // ???
        Pattern pattern = Pattern.compile(dcFormat);
        Matcher matcher = pattern.matcher(propValue);
        if (!matcher.matches()) {
            return false;
        }
        return true;
    }

    /**
     * Cell????.
     * @return Cell??
     */
    public long getPublished() {
        return this.published;
    }
}